mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-24 03:24:55 +08:00
Merge tag 'drm-next-5.6-2019-12-11' of git://people.freedesktop.org/~agd5f/linux into drm-next
drm-next-5.6-2019-12-11: amdgpu: - Add MST atomic routines - Add support for DMCUB (new helper microengine for displays) - Add OEM i2c support in DC - Use vstartup for vblank events on DCN - Simplify Kconfig for DC - Renoir fixes for DC - Clean up function pointers in DC - Initial support for HDCP 2.x - Misc code cleanups - GFX10 fixes - Rework JPEG engine handling for VCN - Add clock and power gating support for JPEG - BACO support for Arcturus - Cleanup PSP ring handling - Add framework for using BACO with runtime pm to save power - Move core pci state handling out of the driver for pm ops - Allow guest power control in 1 VF case with SR-IOV - SR-IOV fixes - RAS fixes - Support for power metrics on renoir - Golden settings updates for gfx10 - Enable gfxoff on supported navi10 skus - Update MAINTAINERS amdkfd: - Clean up generational gfx code - Fixes for gfx10 - DIQ fixes - Share more code with amdgpu radeon: - PPC DMA fix - Register checker fixes for r1xx/r2xx - Misc cleanups From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191211223020.7510-1-alexander.deucher@amd.com
This commit is contained in:
commit
be452c4e8d
@ -2,11 +2,11 @@
|
||||
menu "ACP (Audio CoProcessor) Configuration"
|
||||
|
||||
config DRM_AMD_ACP
|
||||
bool "Enable AMD Audio CoProcessor IP support"
|
||||
depends on DRM_AMDGPU
|
||||
select MFD_CORE
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
bool "Enable AMD Audio CoProcessor IP support"
|
||||
depends on DRM_AMDGPU
|
||||
select MFD_CORE
|
||||
select PM_GENERIC_DOMAINS if PM
|
||||
help
|
||||
Choose this option to enable ACP IP support for AMD SOCs.
|
||||
This adds the ACP (Audio CoProcessor) IP driver and wires
|
||||
it up into the amdgpu driver. The ACP block provides the DMA
|
||||
|
@ -147,12 +147,16 @@ amdgpu-y += \
|
||||
vce_v3_0.o \
|
||||
vce_v4_0.o
|
||||
|
||||
# add VCN block
|
||||
# add VCN and JPEG block
|
||||
amdgpu-y += \
|
||||
amdgpu_vcn.o \
|
||||
vcn_v1_0.o \
|
||||
vcn_v2_0.o \
|
||||
vcn_v2_5.o
|
||||
vcn_v2_5.o \
|
||||
amdgpu_jpeg.o \
|
||||
jpeg_v1_0.o \
|
||||
jpeg_v2_0.o \
|
||||
jpeg_v2_5.o
|
||||
|
||||
# add ATHUB block
|
||||
amdgpu-y += \
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "amdgpu_uvd.h"
|
||||
#include "amdgpu_vce.h"
|
||||
#include "amdgpu_vcn.h"
|
||||
#include "amdgpu_jpeg.h"
|
||||
#include "amdgpu_mn.h"
|
||||
#include "amdgpu_gmc.h"
|
||||
#include "amdgpu_gfx.h"
|
||||
@ -588,6 +589,8 @@ struct amdgpu_asic_funcs {
|
||||
bool (*need_reset_on_init)(struct amdgpu_device *adev);
|
||||
/* PCIe replay counter */
|
||||
uint64_t (*get_pcie_replay_count)(struct amdgpu_device *adev);
|
||||
/* device supports BACO */
|
||||
bool (*supports_baco)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -704,6 +707,7 @@ enum amd_hw_ip_block_type {
|
||||
MP1_HWIP,
|
||||
UVD_HWIP,
|
||||
VCN_HWIP = UVD_HWIP,
|
||||
JPEG_HWIP = VCN_HWIP,
|
||||
VCE_HWIP,
|
||||
DF_HWIP,
|
||||
DCE_HWIP,
|
||||
@ -899,6 +903,9 @@ struct amdgpu_device {
|
||||
/* vcn */
|
||||
struct amdgpu_vcn vcn;
|
||||
|
||||
/* jpeg */
|
||||
struct amdgpu_jpeg jpeg;
|
||||
|
||||
/* firmwares */
|
||||
struct amdgpu_firmware firmware;
|
||||
|
||||
@ -982,6 +989,13 @@ struct amdgpu_device {
|
||||
|
||||
/* device pstate */
|
||||
int pstate;
|
||||
/* enable runtime pm on the device */
|
||||
bool runpm;
|
||||
|
||||
bool pm_sysfs_en;
|
||||
bool ucode_sysfs_en;
|
||||
|
||||
bool in_baco;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
|
||||
@ -1117,6 +1131,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1)))
|
||||
#define amdgpu_asic_need_reset_on_init(adev) (adev)->asic_funcs->need_reset_on_init((adev))
|
||||
#define amdgpu_asic_get_pcie_replay_count(adev) ((adev)->asic_funcs->get_pcie_replay_count((adev)))
|
||||
#define amdgpu_asic_supports_baco(adev) (adev)->asic_funcs->supports_baco((adev))
|
||||
|
||||
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
|
||||
|
||||
/* Common functions */
|
||||
@ -1133,9 +1149,12 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
|
||||
const u32 *registers,
|
||||
const u32 array_size);
|
||||
|
||||
bool amdgpu_device_is_px(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_boco(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_baco(struct drm_device *dev);
|
||||
bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
int amdgpu_device_baco_enter(struct drm_device *dev);
|
||||
int amdgpu_device_baco_exit(struct drm_device *dev);
|
||||
|
||||
/* atpx handler */
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
@ -1173,8 +1192,8 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv);
|
||||
void amdgpu_driver_postclose_kms(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon);
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon);
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
|
||||
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
|
||||
int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
|
||||
void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "soc15d.h"
|
||||
#include "mmhub_v1_0.h"
|
||||
#include "gfxhub_v1_0.h"
|
||||
#include "gmc_v9_0.h"
|
||||
#include "mmhub_v9_4.h"
|
||||
|
||||
|
||||
enum hqd_dequeue_request_type {
|
||||
@ -774,9 +774,7 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmi
|
||||
* on GFX8 and older.
|
||||
*/
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
/* Two MMHUBs */
|
||||
mmhub_v9_4_setup_vm_pt_regs(adev, 0, vmid, page_table_base);
|
||||
mmhub_v9_4_setup_vm_pt_regs(adev, 1, vmid, page_table_base);
|
||||
mmhub_v9_4_setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
} else
|
||||
mmhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base);
|
||||
|
||||
|
@ -85,7 +85,7 @@ static bool check_if_add_bo_to_vm(struct amdgpu_vm *avm,
|
||||
}
|
||||
|
||||
/* Set memory usage limits. Current, limits are
|
||||
* System (TTM + userptr) memory - 3/4th System RAM
|
||||
* System (TTM + userptr) memory - 15/16th System RAM
|
||||
* TTM memory - 3/8th System RAM
|
||||
*/
|
||||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
||||
@ -98,7 +98,7 @@ void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
|
||||
mem *= si.mem_unit;
|
||||
|
||||
spin_lock_init(&kfd_mem_limit.mem_limit_lock);
|
||||
kfd_mem_limit.max_system_mem_limit = (mem >> 1) + (mem >> 2);
|
||||
kfd_mem_limit.max_system_mem_limit = mem - (mem >> 4);
|
||||
kfd_mem_limit.max_ttm_mem_limit = (mem >> 1) - (mem >> 3);
|
||||
pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n",
|
||||
(kfd_mem_limit.max_system_mem_limit >> 20),
|
||||
@ -358,7 +358,7 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return amdgpu_sync_fence(NULL, sync, vm->last_update, false);
|
||||
return amdgpu_sync_fence(sync, vm->last_update, false);
|
||||
}
|
||||
|
||||
static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
|
||||
@ -750,7 +750,7 @@ static int unmap_bo_from_gpuvm(struct amdgpu_device *adev,
|
||||
|
||||
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
|
||||
|
||||
amdgpu_sync_fence(NULL, sync, bo_va->last_pt_update, false);
|
||||
amdgpu_sync_fence(sync, bo_va->last_pt_update, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -769,7 +769,7 @@ static int update_gpuvm_pte(struct amdgpu_device *adev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return amdgpu_sync_fence(NULL, sync, bo_va->last_pt_update, false);
|
||||
return amdgpu_sync_fence(sync, bo_va->last_pt_update, false);
|
||||
}
|
||||
|
||||
static int map_bo_to_gpuvm(struct amdgpu_device *adev,
|
||||
@ -1674,10 +1674,10 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
struct amdkfd_process_info *process_info = mem->process_info;
|
||||
int invalid, evicted_bos;
|
||||
int evicted_bos;
|
||||
int r = 0;
|
||||
|
||||
invalid = atomic_inc_return(&mem->invalid);
|
||||
atomic_inc(&mem->invalid);
|
||||
evicted_bos = atomic_inc_return(&process_info->evicted_bos);
|
||||
if (evicted_bos == 1) {
|
||||
/* First eviction, stop the queues */
|
||||
@ -2048,7 +2048,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
|
||||
pr_debug("Memory eviction: Validate BOs failed. Try again\n");
|
||||
goto validate_map_fail;
|
||||
}
|
||||
ret = amdgpu_sync_fence(NULL, &sync_obj, bo->tbo.moving, false);
|
||||
ret = amdgpu_sync_fence(&sync_obj, bo->tbo.moving, false);
|
||||
if (ret) {
|
||||
pr_debug("Memory eviction: Sync BO fence failed. Try again\n");
|
||||
goto validate_map_fail;
|
||||
|
@ -338,17 +338,9 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *
|
||||
path_size += le16_to_cpu(path->usSize);
|
||||
|
||||
if (device_support & le16_to_cpu(path->usDeviceTag)) {
|
||||
uint8_t con_obj_id, con_obj_num, con_obj_type;
|
||||
|
||||
con_obj_id =
|
||||
uint8_t con_obj_id =
|
||||
(le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
|
||||
>> OBJECT_ID_SHIFT;
|
||||
con_obj_num =
|
||||
(le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
|
||||
>> ENUM_ID_SHIFT;
|
||||
con_obj_type =
|
||||
(le16_to_cpu(path->usConnObjectId) &
|
||||
OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
|
||||
|
||||
/* Skip TV/CV support */
|
||||
if ((le16_to_cpu(path->usDeviceTag) ==
|
||||
@ -373,15 +365,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device *
|
||||
router.ddc_valid = false;
|
||||
router.cd_valid = false;
|
||||
for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
|
||||
uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
|
||||
|
||||
grph_obj_id =
|
||||
(le16_to_cpu(path->usGraphicObjIds[j]) &
|
||||
OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
|
||||
grph_obj_num =
|
||||
(le16_to_cpu(path->usGraphicObjIds[j]) &
|
||||
ENUM_ID_MASK) >> ENUM_ID_SHIFT;
|
||||
grph_obj_type =
|
||||
uint8_t grph_obj_type =
|
||||
(le16_to_cpu(path->usGraphicObjIds[j]) &
|
||||
OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
|
||||
|
||||
|
@ -795,29 +795,23 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_sync_fence(adev, &p->job->sync,
|
||||
fpriv->prt_va->last_pt_update, false);
|
||||
r = amdgpu_sync_vm_fence(&p->job->sync, fpriv->prt_va->last_pt_update);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
|
||||
struct dma_fence *f;
|
||||
|
||||
bo_va = fpriv->csa_va;
|
||||
BUG_ON(!bo_va);
|
||||
r = amdgpu_vm_bo_update(adev, bo_va, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
f = bo_va->last_pt_update;
|
||||
r = amdgpu_sync_fence(adev, &p->job->sync, f, false);
|
||||
r = amdgpu_sync_vm_fence(&p->job->sync, bo_va->last_pt_update);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
|
||||
struct dma_fence *f;
|
||||
|
||||
/* ignore duplicates */
|
||||
bo = ttm_to_amdgpu_bo(e->tv.bo);
|
||||
if (!bo)
|
||||
@ -831,8 +825,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
f = bo_va->last_pt_update;
|
||||
r = amdgpu_sync_fence(adev, &p->job->sync, f, false);
|
||||
r = amdgpu_sync_vm_fence(&p->job->sync, bo_va->last_pt_update);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
@ -845,7 +838,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_sync_fence(adev, &p->job->sync, vm->last_update, false);
|
||||
r = amdgpu_sync_vm_fence(&p->job->sync, vm->last_update);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -987,7 +980,7 @@ static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p,
|
||||
dma_fence_put(old);
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(p->adev, &p->job->sync, fence, true);
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence, true);
|
||||
dma_fence_put(fence);
|
||||
if (r)
|
||||
return r;
|
||||
@ -1009,7 +1002,7 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(struct amdgpu_cs_parser *p,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(p->adev, &p->job->sync, fence, true);
|
||||
r = amdgpu_sync_fence(&p->job->sync, fence, true);
|
||||
dma_fence_put(fence);
|
||||
|
||||
return r;
|
||||
|
@ -169,10 +169,10 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev,
|
||||
}
|
||||
break;
|
||||
case AMDGPU_HW_IP_VCN_JPEG:
|
||||
for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
|
||||
if (adev->vcn.harvest_config & (1 << j))
|
||||
for (j = 0; j < adev->jpeg.num_jpeg_inst; ++j) {
|
||||
if (adev->jpeg.harvest_config & (1 << j))
|
||||
continue;
|
||||
rings[num_rings++] = &adev->vcn.inst[j].ring_jpeg;
|
||||
rings[num_rings++] = &adev->jpeg.inst[j].ring_dec;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -137,14 +137,14 @@ static DEVICE_ATTR(pcie_replay_count, S_IRUGO,
|
||||
static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* amdgpu_device_is_px - Is the device is a dGPU with HG/PX power control
|
||||
* amdgpu_device_supports_boco - Is the device a dGPU with HG/PX power control
|
||||
*
|
||||
* @dev: drm_device pointer
|
||||
*
|
||||
* Returns true if the device is a dGPU with HG/PX power control,
|
||||
* otherwise return false.
|
||||
*/
|
||||
bool amdgpu_device_is_px(struct drm_device *dev)
|
||||
bool amdgpu_device_supports_boco(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
|
||||
@ -153,6 +153,21 @@ bool amdgpu_device_is_px(struct drm_device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_supports_baco - Does the device support BACO
|
||||
*
|
||||
* @dev: drm_device pointer
|
||||
*
|
||||
* Returns true if the device supporte BACO,
|
||||
* otherwise return false.
|
||||
*/
|
||||
bool amdgpu_device_supports_baco(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
|
||||
return amdgpu_asic_supports_baco(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
* VRAM access helper functions.
|
||||
*
|
||||
@ -1072,8 +1087,9 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
|
||||
static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
int r;
|
||||
|
||||
if (amdgpu_device_is_px(dev) && state == VGA_SWITCHEROO_OFF)
|
||||
if (amdgpu_device_supports_boco(dev) && state == VGA_SWITCHEROO_OFF)
|
||||
return;
|
||||
|
||||
if (state == VGA_SWITCHEROO_ON) {
|
||||
@ -1081,7 +1097,12 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
|
||||
/* don't suspend or resume card normally */
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
|
||||
amdgpu_device_resume(dev, true, true);
|
||||
pci_set_power_state(dev->pdev, PCI_D0);
|
||||
pci_restore_state(dev->pdev);
|
||||
r = pci_enable_device(dev->pdev);
|
||||
if (r)
|
||||
DRM_WARN("pci_enable_device failed (%d)\n", r);
|
||||
amdgpu_device_resume(dev, true);
|
||||
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
@ -1089,7 +1110,11 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
|
||||
pr_info("amdgpu: switched off\n");
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
amdgpu_device_suspend(dev, true, true);
|
||||
amdgpu_device_suspend(dev, true);
|
||||
pci_save_state(dev->pdev);
|
||||
/* Shut down the device */
|
||||
pci_disable_device(dev->pdev);
|
||||
pci_set_power_state(dev->pdev, PCI_D3cold);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||
}
|
||||
}
|
||||
@ -1527,7 +1552,6 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
parse_soc_bounding_box:
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
/*
|
||||
* soc bounding box info is not integrated in disocovery table,
|
||||
* we always need to parse it from gpu info firmware.
|
||||
@ -1538,7 +1562,6 @@ parse_soc_bounding_box:
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||
adev->dm.soc_bounding_box = &gpu_info_fw->soc_bounding_box;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1854,6 +1877,9 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
|
||||
r = amdgpu_ib_pool_init(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "IB initialization failed (%d).\n", r);
|
||||
@ -1895,11 +1921,8 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
||||
amdgpu_amdkfd_device_init(adev);
|
||||
|
||||
init_failed:
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (!r)
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -1938,6 +1961,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
|
||||
* amdgpu_device_set_cg_state - set clockgating for amdgpu device
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @state: clockgating state (gate or ungate)
|
||||
*
|
||||
* The list of all the hardware IPs that make up the asic is walked and the
|
||||
* set_clockgating_state callbacks are run.
|
||||
@ -1962,6 +1986,7 @@ static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
|
||||
adev->ip_blocks[i].version->funcs->set_clockgating_state) {
|
||||
/* enable clockgating to save power */
|
||||
r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
|
||||
@ -1992,6 +2017,7 @@ static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_power
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCN &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_JPEG &&
|
||||
adev->ip_blocks[i].version->funcs->set_powergating_state) {
|
||||
/* enable powergating to save power */
|
||||
r = adev->ip_blocks[i].version->funcs->set_powergating_state((void *)adev,
|
||||
@ -2600,20 +2626,19 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
case CHIP_RAVEN:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
|
||||
case CHIP_RENOIR:
|
||||
#endif
|
||||
return amdgpu_dc != 0;
|
||||
#endif
|
||||
default:
|
||||
if (amdgpu_dc > 0)
|
||||
DRM_INFO("Display Core has been requested via kernel parameter "
|
||||
"but isn't supported by ASIC, ignoring\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2639,7 +2664,13 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
|
||||
struct amdgpu_device *adev =
|
||||
container_of(__work, struct amdgpu_device, xgmi_reset_work);
|
||||
|
||||
adev->asic_reset_res = amdgpu_asic_reset(adev);
|
||||
if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)
|
||||
adev->asic_reset_res = (adev->in_baco == false) ?
|
||||
amdgpu_device_baco_enter(adev->ddev) :
|
||||
amdgpu_device_baco_exit(adev->ddev);
|
||||
else
|
||||
adev->asic_reset_res = amdgpu_asic_reset(adev);
|
||||
|
||||
if (adev->asic_reset_res)
|
||||
DRM_WARN("ASIC reset failed with error, %d for drm dev, %s",
|
||||
adev->asic_reset_res, adev->ddev->unique);
|
||||
@ -2731,7 +2762,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r, i;
|
||||
bool runtime = false;
|
||||
bool boco = false;
|
||||
u32 max_MBps;
|
||||
|
||||
adev->shutdown = false;
|
||||
@ -2794,8 +2825,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
mutex_init(&adev->virt.vf_errors.lock);
|
||||
hash_init(adev->mn_hash);
|
||||
mutex_init(&adev->lock_reset);
|
||||
mutex_init(&adev->notifier_lock);
|
||||
mutex_init(&adev->virt.dpm_mutex);
|
||||
mutex_init(&adev->psp.mutex);
|
||||
|
||||
r = amdgpu_device_check_arguments(adev);
|
||||
@ -2902,12 +2931,15 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
* ignore it */
|
||||
vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
|
||||
|
||||
if (amdgpu_device_is_px(ddev))
|
||||
runtime = true;
|
||||
if (!pci_is_thunderbolt_attached(adev->pdev))
|
||||
if (amdgpu_device_supports_boco(ddev))
|
||||
boco = true;
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
!pci_is_thunderbolt_attached(adev->pdev))
|
||||
vga_switcheroo_register_client(adev->pdev,
|
||||
&amdgpu_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
&amdgpu_switcheroo_ops, boco);
|
||||
if (boco)
|
||||
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
|
||||
|
||||
if (amdgpu_emu_mode == 1) {
|
||||
@ -2994,8 +3026,6 @@ fence_driver_init:
|
||||
}
|
||||
dev_err(adev->dev, "amdgpu_device_ip_init failed\n");
|
||||
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0);
|
||||
if (amdgpu_virt_request_full_gpu(adev, false))
|
||||
amdgpu_virt_release_full_gpu(adev, false);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -3013,16 +3043,19 @@ fence_driver_init:
|
||||
|
||||
amdgpu_fbdev_init(adev);
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev))
|
||||
amdgpu_pm_virt_sysfs_init(adev);
|
||||
|
||||
r = amdgpu_pm_sysfs_init(adev);
|
||||
if (r)
|
||||
if (r) {
|
||||
adev->pm_sysfs_en = false;
|
||||
DRM_ERROR("registering pm debugfs failed (%d).\n", r);
|
||||
} else
|
||||
adev->pm_sysfs_en = true;
|
||||
|
||||
r = amdgpu_ucode_sysfs_init(adev);
|
||||
if (r)
|
||||
if (r) {
|
||||
adev->ucode_sysfs_en = false;
|
||||
DRM_ERROR("Creating firmware sysfs failed (%d).\n", r);
|
||||
} else
|
||||
adev->ucode_sysfs_en = true;
|
||||
|
||||
r = amdgpu_debugfs_gem_init(adev);
|
||||
if (r)
|
||||
@ -3091,7 +3124,7 @@ fence_driver_init:
|
||||
|
||||
failed:
|
||||
amdgpu_vf_error_trans_all(adev);
|
||||
if (runtime)
|
||||
if (boco)
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
|
||||
return r;
|
||||
@ -3122,7 +3155,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
drm_atomic_helper_shutdown(adev->ddev);
|
||||
}
|
||||
amdgpu_fence_driver_fini(adev);
|
||||
amdgpu_pm_sysfs_fini(adev);
|
||||
if (adev->pm_sysfs_en)
|
||||
amdgpu_pm_sysfs_fini(adev);
|
||||
amdgpu_fbdev_fini(adev);
|
||||
r = amdgpu_device_ip_fini(adev);
|
||||
if (adev->firmware.gpu_info_fw) {
|
||||
@ -3139,9 +3173,12 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
|
||||
kfree(adev->bios);
|
||||
adev->bios = NULL;
|
||||
if (!pci_is_thunderbolt_attached(adev->pdev))
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
!pci_is_thunderbolt_attached(adev->pdev))
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
if (adev->flags & AMD_IS_PX)
|
||||
if (amdgpu_device_supports_boco(adev->ddev))
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
if (adev->rio_mem)
|
||||
@ -3150,12 +3187,11 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
iounmap(adev->rmmio);
|
||||
adev->rmmio = NULL;
|
||||
amdgpu_device_doorbell_fini(adev);
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev))
|
||||
amdgpu_pm_virt_sysfs_fini(adev);
|
||||
|
||||
amdgpu_debugfs_regs_cleanup(adev);
|
||||
device_remove_file(adev->dev, &dev_attr_pcie_replay_count);
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
if (adev->ucode_sysfs_en)
|
||||
amdgpu_ucode_sysfs_fini(adev);
|
||||
if (IS_ENABLED(CONFIG_PERF_EVENTS))
|
||||
amdgpu_pmu_fini(adev);
|
||||
amdgpu_debugfs_preempt_cleanup(adev);
|
||||
@ -3178,7 +3214,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
* Returns 0 for success or an error on failure.
|
||||
* Called at driver suspend.
|
||||
*/
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_crtc *crtc;
|
||||
@ -3261,13 +3297,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
|
||||
*/
|
||||
amdgpu_bo_evict_vram(adev);
|
||||
|
||||
if (suspend) {
|
||||
pci_save_state(dev->pdev);
|
||||
/* Shut down the device */
|
||||
pci_disable_device(dev->pdev);
|
||||
pci_set_power_state(dev->pdev, PCI_D3hot);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3282,7 +3311,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
|
||||
* Returns 0 for success or an error on failure.
|
||||
* Called at driver resume.
|
||||
*/
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
@ -3293,14 +3322,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
if (resume) {
|
||||
pci_set_power_state(dev->pdev, PCI_D0);
|
||||
pci_restore_state(dev->pdev);
|
||||
r = pci_enable_device(dev->pdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* post card */
|
||||
if (amdgpu_device_need_post(adev)) {
|
||||
r = amdgpu_atom_asic_init(adev->mode_info.atom_context);
|
||||
@ -3646,6 +3667,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
/* we need recover gart prior to run SMC/CP/SDMA resume */
|
||||
amdgpu_gtt_mgr_recover(&adev->mman.bdev.man[TTM_PL_TT]);
|
||||
|
||||
@ -3663,7 +3685,6 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
amdgpu_amdkfd_post_reset(adev);
|
||||
|
||||
error:
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
|
||||
amdgpu_inc_vram_lost(adev);
|
||||
@ -3769,13 +3790,18 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
static int amdgpu_do_asic_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_hive_info *hive,
|
||||
struct list_head *device_list_handle,
|
||||
bool *need_full_reset_arg)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
bool need_full_reset = *need_full_reset_arg, vram_lost = false;
|
||||
int r = 0;
|
||||
int cpu = smp_processor_id();
|
||||
bool use_baco =
|
||||
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) ?
|
||||
true : false;
|
||||
|
||||
/*
|
||||
* ASIC reset has to be done on all HGMI hive nodes ASAP
|
||||
@ -3783,21 +3809,24 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
*/
|
||||
if (need_full_reset) {
|
||||
list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
|
||||
/* For XGMI run all resets in parallel to speed up the process */
|
||||
/*
|
||||
* For XGMI run all resets in parallel to speed up the
|
||||
* process by scheduling the highpri wq on different
|
||||
* cpus. For XGMI with baco reset, all nodes must enter
|
||||
* baco within close proximity before anyone exit.
|
||||
*/
|
||||
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!queue_work(system_highpri_wq, &tmp_adev->xgmi_reset_work))
|
||||
if (!queue_work_on(cpu, system_highpri_wq,
|
||||
&tmp_adev->xgmi_reset_work))
|
||||
r = -EALREADY;
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
} else
|
||||
r = amdgpu_asic_reset(tmp_adev);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s",
|
||||
r, tmp_adev->ddev->unique);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* For XGMI wait for all PSP resets to complete before proceed */
|
||||
/* For XGMI wait for all work to complete before proceed */
|
||||
if (!r) {
|
||||
list_for_each_entry(tmp_adev, device_list_handle,
|
||||
gmc.xgmi.head) {
|
||||
@ -3806,11 +3835,57 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
r = tmp_adev->asic_reset_res;
|
||||
if (r)
|
||||
break;
|
||||
if (use_baco)
|
||||
tmp_adev->in_baco = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For XGMI with baco reset, need exit baco phase by scheduling
|
||||
* xgmi_reset_work one more time. PSP reset and sGPU skips this
|
||||
* phase. Not assume the situation that PSP reset and baco reset
|
||||
* coexist within an XGMI hive.
|
||||
*/
|
||||
|
||||
if (!r && use_baco) {
|
||||
cpu = smp_processor_id();
|
||||
list_for_each_entry(tmp_adev, device_list_handle,
|
||||
gmc.xgmi.head) {
|
||||
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!queue_work_on(cpu,
|
||||
system_highpri_wq,
|
||||
&tmp_adev->xgmi_reset_work))
|
||||
r = -EALREADY;
|
||||
if (r)
|
||||
break;
|
||||
cpu = cpumask_next(cpu, cpu_online_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!r && use_baco) {
|
||||
list_for_each_entry(tmp_adev, device_list_handle,
|
||||
gmc.xgmi.head) {
|
||||
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
flush_work(&tmp_adev->xgmi_reset_work);
|
||||
r = tmp_adev->asic_reset_res;
|
||||
if (r)
|
||||
break;
|
||||
tmp_adev->in_baco = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s",
|
||||
r, tmp_adev->ddev->unique);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!r && amdgpu_ras_intr_triggered())
|
||||
amdgpu_ras_intr_cleared();
|
||||
|
||||
list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
|
||||
if (need_full_reset) {
|
||||
@ -3943,12 +4018,15 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
int i, r = 0;
|
||||
bool in_ras_intr = amdgpu_ras_intr_triggered();
|
||||
bool use_baco =
|
||||
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) ?
|
||||
true : false;
|
||||
|
||||
/*
|
||||
* Flush RAM to disk so that after reboot
|
||||
* the user can read log and see why the system rebooted.
|
||||
*/
|
||||
if (in_ras_intr && amdgpu_ras_get_context(adev)->reboot) {
|
||||
if (in_ras_intr && !use_baco && amdgpu_ras_get_context(adev)->reboot) {
|
||||
|
||||
DRM_WARN("Emergency reboot.");
|
||||
|
||||
@ -3959,7 +4037,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
need_full_reset = job_signaled = false;
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
|
||||
dev_info(adev->dev, "GPU %s begin!\n", in_ras_intr ? "jobs stop":"reset");
|
||||
dev_info(adev->dev, "GPU %s begin!\n",
|
||||
(in_ras_intr && !use_baco) ? "jobs stop":"reset");
|
||||
|
||||
cancel_delayed_work_sync(&adev->delayed_init_work);
|
||||
|
||||
@ -4026,7 +4105,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
amdgpu_unregister_gpu_instance(tmp_adev);
|
||||
|
||||
/* disable ras on ALL IPs */
|
||||
if (!in_ras_intr && amdgpu_device_ip_need_full_reset(tmp_adev))
|
||||
if (!(in_ras_intr && !use_baco) &&
|
||||
amdgpu_device_ip_need_full_reset(tmp_adev))
|
||||
amdgpu_ras_suspend(tmp_adev);
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
@ -4037,13 +4117,13 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
|
||||
drm_sched_stop(&ring->sched, job ? &job->base : NULL);
|
||||
|
||||
if (in_ras_intr)
|
||||
if (in_ras_intr && !use_baco)
|
||||
amdgpu_job_stop_all_jobs_on_sched(&ring->sched);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (in_ras_intr)
|
||||
if (in_ras_intr && !use_baco)
|
||||
goto skip_sched_resume;
|
||||
|
||||
/*
|
||||
@ -4095,7 +4175,8 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
if (r)
|
||||
adev->asic_reset_res = r;
|
||||
} else {
|
||||
r = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset);
|
||||
r = amdgpu_do_asic_reset(adev, hive, device_list_handle,
|
||||
&need_full_reset);
|
||||
if (r && r == -EAGAIN)
|
||||
goto retry;
|
||||
}
|
||||
@ -4136,7 +4217,7 @@ skip_hw_reset:
|
||||
skip_sched_resume:
|
||||
list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) {
|
||||
/*unlock kfd: SRIOV would do it separately */
|
||||
if (!in_ras_intr && !amdgpu_sriov_vf(tmp_adev))
|
||||
if (!(in_ras_intr && !use_baco) && !amdgpu_sriov_vf(tmp_adev))
|
||||
amdgpu_amdkfd_post_reset(tmp_adev);
|
||||
amdgpu_device_unlock_adev(tmp_adev);
|
||||
}
|
||||
@ -4285,3 +4366,69 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_device_baco_enter(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (!amdgpu_device_supports_baco(adev->ddev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (ras && ras->supported)
|
||||
adev->nbio.funcs->enable_doorbell_interrupt(adev, false);
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
struct smu_context *smu = &adev->smu;
|
||||
int ret;
|
||||
|
||||
ret = smu_baco_enter(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
|
||||
return -ENOENT;
|
||||
|
||||
/* enter BACO state */
|
||||
if (pp_funcs->set_asic_baco_state(pp_handle, 1))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_device_baco_exit(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (!amdgpu_device_supports_baco(adev->ddev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
struct smu_context *smu = &adev->smu;
|
||||
int ret;
|
||||
|
||||
ret = smu_baco_exit(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state)
|
||||
return -ENOENT;
|
||||
|
||||
/* exit BACO state */
|
||||
if (pp_funcs->set_asic_baco_state(pp_handle, 0))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ras && ras->supported)
|
||||
adev->nbio.funcs->enable_doorbell_interrupt(adev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -690,7 +690,6 @@ bool amdgpu_display_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
||||
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||
struct amdgpu_encoder *amdgpu_encoder;
|
||||
struct drm_connector *connector;
|
||||
struct amdgpu_connector *amdgpu_connector;
|
||||
u32 src_v = 1, dst_v = 1;
|
||||
u32 src_h = 1, dst_h = 1;
|
||||
|
||||
@ -702,7 +701,6 @@ bool amdgpu_display_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
||||
continue;
|
||||
amdgpu_encoder = to_amdgpu_encoder(encoder);
|
||||
connector = amdgpu_get_connector_for_encoder(encoder);
|
||||
amdgpu_connector = to_amdgpu_connector(connector);
|
||||
|
||||
/* set scaling */
|
||||
if (amdgpu_encoder->rmx_type == RMX_OFF)
|
||||
|
@ -1147,7 +1147,7 @@ static int amdgpu_pmops_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return amdgpu_device_suspend(drm_dev, true, true);
|
||||
return amdgpu_device_suspend(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_resume(struct device *dev)
|
||||
@ -1155,13 +1155,14 @@ static int amdgpu_pmops_resume(struct device *dev)
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
/* GPU comes up enabled by the bios on resume */
|
||||
if (amdgpu_device_is_px(drm_dev)) {
|
||||
if (amdgpu_device_supports_boco(drm_dev) ||
|
||||
amdgpu_device_supports_baco(drm_dev)) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
|
||||
return amdgpu_device_resume(drm_dev, true, true);
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_freeze(struct device *dev)
|
||||
@ -1170,7 +1171,7 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||
int r;
|
||||
|
||||
r = amdgpu_device_suspend(drm_dev, false, true);
|
||||
r = amdgpu_device_suspend(drm_dev, true);
|
||||
if (r)
|
||||
return r;
|
||||
return amdgpu_asic_reset(adev);
|
||||
@ -1180,46 +1181,56 @@ static int amdgpu_pmops_thaw(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return amdgpu_device_resume(drm_dev, false, true);
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_poweroff(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return amdgpu_device_suspend(drm_dev, true, true);
|
||||
return amdgpu_device_suspend(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_restore(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return amdgpu_device_resume(drm_dev, false, true);
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (!amdgpu_device_is_px(drm_dev)) {
|
||||
if (!adev->runpm) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
if (amdgpu_device_supports_boco(drm_dev))
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
drm_kms_helper_poll_disable(drm_dev);
|
||||
|
||||
ret = amdgpu_device_suspend(drm_dev, false, false);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_ignore_hotplug(pdev);
|
||||
if (amdgpu_is_atpx_hybrid())
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
else if (!amdgpu_has_atpx_dgpu_power_cntl())
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
|
||||
ret = amdgpu_device_suspend(drm_dev, false);
|
||||
if (amdgpu_device_supports_boco(drm_dev)) {
|
||||
/* Only need to handle PCI state in the driver for ATPX
|
||||
* PCI core handles it for _PR3.
|
||||
*/
|
||||
if (amdgpu_is_atpx_hybrid()) {
|
||||
pci_ignore_hotplug(pdev);
|
||||
} else {
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_ignore_hotplug(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
}
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
|
||||
} else if (amdgpu_device_supports_baco(drm_dev)) {
|
||||
amdgpu_device_baco_enter(drm_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1228,34 +1239,45 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (!amdgpu_device_is_px(drm_dev))
|
||||
if (!adev->runpm)
|
||||
return -EINVAL;
|
||||
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
if (amdgpu_device_supports_boco(drm_dev)) {
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
|
||||
if (amdgpu_is_atpx_hybrid() ||
|
||||
!amdgpu_has_atpx_dgpu_power_cntl())
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = amdgpu_device_resume(drm_dev, false, false);
|
||||
/* Only need to handle PCI state in the driver for ATPX
|
||||
* PCI core handles it for _PR3.
|
||||
*/
|
||||
if (amdgpu_is_atpx_hybrid()) {
|
||||
pci_set_master(pdev);
|
||||
} else {
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pci_set_master(pdev);
|
||||
}
|
||||
} else if (amdgpu_device_supports_baco(drm_dev)) {
|
||||
amdgpu_device_baco_exit(drm_dev);
|
||||
}
|
||||
ret = amdgpu_device_resume(drm_dev, false);
|
||||
drm_kms_helper_poll_enable(drm_dev);
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||
if (amdgpu_device_supports_boco(drm_dev))
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (!amdgpu_device_is_px(drm_dev)) {
|
||||
if (!adev->runpm) {
|
||||
pm_runtime_forbid(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -302,6 +302,7 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
* @pages: number of pages to bind
|
||||
* @pagelist: pages to bind
|
||||
* @dma_addr: DMA addresses of pages
|
||||
* @flags: page table entry flags
|
||||
*
|
||||
* Binds the requested pages to the gart page table
|
||||
* (all asics).
|
||||
|
@ -206,7 +206,7 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
|
||||
int r;
|
||||
|
||||
if (ring->vmid_wait && !dma_fence_is_signaled(ring->vmid_wait))
|
||||
return amdgpu_sync_fence(adev, sync, ring->vmid_wait, false);
|
||||
return amdgpu_sync_fence(sync, ring->vmid_wait, false);
|
||||
|
||||
fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL);
|
||||
if (!fences)
|
||||
@ -241,7 +241,7 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(adev, sync, &array->base, false);
|
||||
r = amdgpu_sync_fence(sync, &array->base, false);
|
||||
dma_fence_put(ring->vmid_wait);
|
||||
ring->vmid_wait = &array->base;
|
||||
return r;
|
||||
@ -294,7 +294,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
|
||||
tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
|
||||
if (tmp) {
|
||||
*id = NULL;
|
||||
r = amdgpu_sync_fence(adev, sync, tmp, false);
|
||||
r = amdgpu_sync_fence(sync, tmp, false);
|
||||
return r;
|
||||
}
|
||||
needs_flush = true;
|
||||
@ -303,7 +303,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
|
||||
/* Good we can use this VMID. Remember this submission as
|
||||
* user of the VMID.
|
||||
*/
|
||||
r = amdgpu_sync_fence(ring->adev, &(*id)->active, fence, false);
|
||||
r = amdgpu_sync_fence(&(*id)->active, fence, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -375,7 +375,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
|
||||
/* Good, we can use this VMID. Remember this submission as
|
||||
* user of the VMID.
|
||||
*/
|
||||
r = amdgpu_sync_fence(ring->adev, &(*id)->active, fence, false);
|
||||
r = amdgpu_sync_fence(&(*id)->active, fence, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -435,8 +435,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||
id = idle;
|
||||
|
||||
/* Remember this submission as user of the VMID */
|
||||
r = amdgpu_sync_fence(ring->adev, &id->active,
|
||||
fence, false);
|
||||
r = amdgpu_sync_fence(&id->active, fence, false);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
|
@ -66,7 +66,6 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
if (ih->ring == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset((void *)ih->ring, 0, ih->ring_size + 8);
|
||||
ih->gpu_addr = dma_addr;
|
||||
ih->wptr_addr = dma_addr + ih->ring_size;
|
||||
ih->wptr_cpu = &ih->ring[ih->ring_size / 4];
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "amdgpu_connectors.h"
|
||||
#include "amdgpu_trace.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
@ -162,13 +163,15 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
||||
* register to check whether the interrupt is triggered or not, and properly
|
||||
* ack the interrupt if it is there
|
||||
*/
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring(adev);
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) {
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring(adev);
|
||||
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -193,8 +193,7 @@ static struct dma_fence *amdgpu_job_dependency(struct drm_sched_job *sched_job,
|
||||
fence = amdgpu_sync_get_fence(&job->sync, &explicit);
|
||||
if (fence && explicit) {
|
||||
if (drm_sched_dependency_optimized(fence, s_entity)) {
|
||||
r = amdgpu_sync_fence(ring->adev, &job->sched_sync,
|
||||
fence, false);
|
||||
r = amdgpu_sync_fence(&job->sched_sync, fence, false);
|
||||
if (r)
|
||||
DRM_ERROR("Error adding fence (%d)\n", r);
|
||||
}
|
||||
|
211
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
Normal file
211
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_jpeg.h"
|
||||
#include "amdgpu_pm.h"
|
||||
#include "soc15d.h"
|
||||
#include "soc15_common.h"
|
||||
|
||||
#define JPEG_IDLE_TIMEOUT msecs_to_jiffies(1000)
|
||||
|
||||
static void amdgpu_jpeg_idle_work_handler(struct work_struct *work);
|
||||
|
||||
int amdgpu_jpeg_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
INIT_DELAYED_WORK(&adev->jpeg.idle_work, amdgpu_jpeg_idle_work_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
cancel_delayed_work_sync(&adev->jpeg.idle_work);
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
amdgpu_ring_fini(&adev->jpeg.inst[i].ring_dec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_jpeg_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
cancel_delayed_work_sync(&adev->jpeg.idle_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_jpeg_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_jpeg_idle_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev =
|
||||
container_of(work, struct amdgpu_device, jpeg.idle_work.work);
|
||||
unsigned int fences = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec);
|
||||
}
|
||||
|
||||
if (fences == 0)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
else
|
||||
schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
bool set_clocks = !cancel_delayed_work_sync(&adev->jpeg.idle_work);
|
||||
|
||||
if (set_clocks)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
}
|
||||
|
||||
void amdgpu_jpeg_ring_end_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
schedule_delayed_work(&ring->adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
int amdgpu_jpeg_dec_ring_test_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
WREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD);
|
||||
r = amdgpu_ring_alloc(ring, 3);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_ring_write(ring, PACKET0(adev->jpeg.internal.jpeg_pitch, 0));
|
||||
amdgpu_ring_write(ring, 0xDEADBEEF);
|
||||
amdgpu_ring_commit(ring);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct dma_fence *f = NULL;
|
||||
const unsigned ib_size_dw = 16;
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
|
||||
ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0);
|
||||
ib->ptr[1] = 0xDEADBEEF;
|
||||
for (i = 2; i < 16; i += 2) {
|
||||
ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
ib->ptr[i+1] = 0;
|
||||
}
|
||||
ib->length_dw = 16;
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (fence)
|
||||
*fence = dma_fence_get(f);
|
||||
dma_fence_put(f);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
amdgpu_job_free(job);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
struct dma_fence *fence = NULL;
|
||||
long r = 0;
|
||||
|
||||
r = amdgpu_jpeg_dec_set_reg(ring, 1, &fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = dma_fence_wait_timeout(fence, false, timeout);
|
||||
if (r == 0) {
|
||||
r = -ETIMEDOUT;
|
||||
goto error;
|
||||
} else if (r < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(adev->jpeg.inst[ring->me].external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
dma_fence_put(fence);
|
||||
error:
|
||||
return r;
|
||||
}
|
62
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
Normal file
62
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_JPEG_H__
|
||||
#define __AMDGPU_JPEG_H__
|
||||
|
||||
#define AMDGPU_MAX_JPEG_INSTANCES 2
|
||||
|
||||
#define AMDGPU_JPEG_HARVEST_JPEG0 (1 << 0)
|
||||
#define AMDGPU_JPEG_HARVEST_JPEG1 (1 << 1)
|
||||
|
||||
struct amdgpu_jpeg_reg{
|
||||
unsigned jpeg_pitch;
|
||||
};
|
||||
|
||||
struct amdgpu_jpeg_inst {
|
||||
struct amdgpu_ring ring_dec;
|
||||
struct amdgpu_irq_src irq;
|
||||
struct amdgpu_jpeg_reg external;
|
||||
};
|
||||
|
||||
struct amdgpu_jpeg {
|
||||
uint8_t num_jpeg_inst;
|
||||
struct amdgpu_jpeg_inst inst[AMDGPU_MAX_JPEG_INSTANCES];
|
||||
struct amdgpu_jpeg_reg internal;
|
||||
unsigned harvest_config;
|
||||
struct delayed_work idle_work;
|
||||
enum amd_powergating_state cur_state;
|
||||
};
|
||||
|
||||
int amdgpu_jpeg_sw_init(struct amdgpu_device *adev);
|
||||
int amdgpu_jpeg_sw_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_jpeg_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_jpeg_resume(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_jpeg_ring_begin_use(struct amdgpu_ring *ring);
|
||||
void amdgpu_jpeg_ring_end_use(struct amdgpu_ring *ring);
|
||||
|
||||
int amdgpu_jpeg_dec_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
|
||||
#endif /*__AMDGPU_JPEG_H__*/
|
@ -91,7 +91,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_request_full_gpu(adev, false);
|
||||
|
||||
if (amdgpu_device_is_px(dev)) {
|
||||
if (adev->runpm) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
pm_runtime_forbid(dev->dev);
|
||||
}
|
||||
@ -150,8 +150,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
||||
}
|
||||
dev->dev_private = (void *)adev;
|
||||
|
||||
if ((amdgpu_runtime_pm != 0) &&
|
||||
amdgpu_has_atpx() &&
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
((flags & AMD_IS_APU) == 0) &&
|
||||
@ -170,6 +169,13 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (amdgpu_device_supports_boco(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) /* enable runpm by default */
|
||||
adev->runpm = true;
|
||||
else if (amdgpu_device_supports_baco(dev) &&
|
||||
(amdgpu_runtime_pm > 0)) /* enable runpm if runpm=1 */
|
||||
adev->runpm = true;
|
||||
|
||||
/* Call ACPI methods: require modeset init
|
||||
* but failure is not fatal
|
||||
*/
|
||||
@ -180,7 +186,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
||||
"Error during ACPI methods call\n");
|
||||
}
|
||||
|
||||
if (amdgpu_device_is_px(dev)) {
|
||||
if (adev->runpm) {
|
||||
dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP);
|
||||
pm_runtime_use_autosuspend(dev->dev);
|
||||
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
|
||||
@ -193,7 +199,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
||||
out:
|
||||
if (r) {
|
||||
/* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
|
||||
if (adev->rmmio && amdgpu_device_is_px(dev))
|
||||
if (adev->rmmio && adev->runpm)
|
||||
pm_runtime_put_noidle(dev->dev);
|
||||
amdgpu_driver_unload_kms(dev);
|
||||
}
|
||||
@ -293,6 +299,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
|
||||
fw_info->ver = adev->dm.dmcu_fw_version;
|
||||
fw_info->feature = 0;
|
||||
break;
|
||||
case AMDGPU_INFO_FW_DMCUB:
|
||||
fw_info->ver = adev->dm.dmcub_fw_version;
|
||||
fw_info->feature = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -396,12 +406,14 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
|
||||
ib_size_alignment = 1;
|
||||
break;
|
||||
case AMDGPU_HW_IP_VCN_JPEG:
|
||||
type = AMD_IP_BLOCK_TYPE_VCN;
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
|
||||
if (adev->uvd.harvest_config & (1 << i))
|
||||
type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
|
||||
AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
if (adev->vcn.inst[i].ring_jpeg.sched.ready)
|
||||
if (adev->jpeg.inst[i].ring_dec.sched.ready)
|
||||
++num_rings;
|
||||
}
|
||||
ib_start_alignment = 16;
|
||||
@ -517,9 +529,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
||||
break;
|
||||
case AMDGPU_HW_IP_VCN_DEC:
|
||||
case AMDGPU_HW_IP_VCN_ENC:
|
||||
case AMDGPU_HW_IP_VCN_JPEG:
|
||||
type = AMD_IP_BLOCK_TYPE_VCN;
|
||||
break;
|
||||
case AMDGPU_HW_IP_VCN_JPEG:
|
||||
type = (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_JPEG)) ?
|
||||
AMD_IP_BLOCK_TYPE_JPEG : AMD_IP_BLOCK_TYPE_VCN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -688,10 +703,6 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
||||
if (adev->pm.dpm_enabled) {
|
||||
dev_info.max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10;
|
||||
dev_info.max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;
|
||||
} else if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
|
||||
adev->virt.ops->get_pp_clk) {
|
||||
dev_info.max_engine_clock = amdgpu_virt_get_sclk(adev, false) * 10;
|
||||
dev_info.max_memory_clock = amdgpu_virt_get_mclk(adev, false) * 10;
|
||||
} else {
|
||||
dev_info.max_engine_clock = adev->clock.default_sclk * 10;
|
||||
dev_info.max_memory_clock = adev->clock.default_mclk * 10;
|
||||
@ -1394,6 +1405,14 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data)
|
||||
seq_printf(m, "DMCU feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
|
||||
/* DMCUB */
|
||||
query_fw.fw_type = AMDGPU_INFO_FW_DMCUB;
|
||||
ret = amdgpu_firmware_info(&fw_info, &query_fw, adev);
|
||||
if (ret)
|
||||
return ret;
|
||||
seq_printf(m, "DMCUB feature version: %u, firmware version: 0x%08x\n",
|
||||
fw_info.feature, fw_info.ver);
|
||||
|
||||
|
||||
seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version);
|
||||
|
||||
|
@ -159,6 +159,9 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
enum amd_pm_state_type pm;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
if (adev->smu.ppt_funcs->get_current_power_state)
|
||||
pm = smu_get_current_power_state(&adev->smu);
|
||||
@ -184,6 +187,9 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
enum amd_pm_state_type state;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (strncmp("battery", buf, strlen("battery")) == 0)
|
||||
state = POWER_STATE_TYPE_BATTERY;
|
||||
else if (strncmp("balanced", buf, strlen("balanced")) == 0)
|
||||
@ -283,7 +289,7 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
enum amd_dpm_forced_level level = 0xff;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
@ -320,6 +326,9 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
||||
enum amd_dpm_forced_level current_level = 0xff;
|
||||
int ret = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
/* Can't force performance level when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
@ -348,19 +357,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* handle sriov case here */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (amdgim_is_hwperf(adev) &&
|
||||
adev->virt.ops->force_dpm_level) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->virt.ops->force_dpm_level(adev, level);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return count;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
current_level = smu_get_performance_level(&adev->smu);
|
||||
else if (adev->powerplay.pp_funcs->get_performance_level)
|
||||
@ -440,6 +436,9 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev,
|
||||
enum amd_pm_state_type pm = 0;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
pm = smu_get_current_power_state(smu);
|
||||
ret = smu_get_power_num_states(smu, &data);
|
||||
@ -469,6 +468,9 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (adev->pp_force_state_enabled)
|
||||
return amdgpu_get_pp_cur_state(dev, attr, buf);
|
||||
else
|
||||
@ -486,6 +488,9 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
|
||||
unsigned long idx;
|
||||
int ret;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (strlen(buf) == 1)
|
||||
adev->pp_force_state_enabled = false;
|
||||
else if (is_support_sw_smu(adev))
|
||||
@ -535,6 +540,9 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
|
||||
char *table = NULL;
|
||||
int size;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
size = smu_sys_get_pp_table(&adev->smu, (void **)&table);
|
||||
if (size < 0)
|
||||
@ -562,6 +570,9 @@ static ssize_t amdgpu_set_pp_table(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int ret = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_sys_set_pp_table(&adev->smu, (void *)buf, count);
|
||||
if (ret)
|
||||
@ -654,6 +665,9 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
||||
const char delimiter[3] = {' ', '\n', '\0'};
|
||||
uint32_t type;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (count > 127)
|
||||
return -EINVAL;
|
||||
|
||||
@ -726,6 +740,9 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint32_t size = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
size = smu_print_clk_levels(&adev->smu, SMU_OD_SCLK, buf);
|
||||
size += smu_print_clk_levels(&adev->smu, SMU_OD_MCLK, buf+size);
|
||||
@ -770,6 +787,9 @@ static ssize_t amdgpu_set_pp_feature_status(struct device *dev,
|
||||
uint64_t featuremask;
|
||||
int ret;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtou64(buf, 0, &featuremask);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
@ -796,6 +816,9 @@ static ssize_t amdgpu_get_pp_feature_status(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
return smu_sys_get_pp_feature_mask(&adev->smu, buf);
|
||||
} else if (adev->powerplay.pp_funcs->get_ppfeature_status)
|
||||
@ -841,9 +864,8 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
|
||||
adev->virt.ops->get_pp_clk)
|
||||
return adev->virt.ops->get_pp_clk(adev, PP_SCLK, buf);
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_SCLK, buf);
|
||||
@ -899,8 +921,8 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
@ -924,9 +946,8 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev) &&
|
||||
adev->virt.ops->get_pp_clk)
|
||||
return adev->virt.ops->get_pp_clk(adev, PP_MCLK, buf);
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_MCLK, buf);
|
||||
@ -946,8 +967,8 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
@ -971,6 +992,9 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_SOCCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
@ -989,6 +1013,9 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1011,6 +1038,9 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_FCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
@ -1029,6 +1059,9 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1051,6 +1084,9 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_DCEFCLK, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
@ -1069,6 +1105,9 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1091,6 +1130,9 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_print_clk_levels(&adev->smu, SMU_PCIE, buf);
|
||||
else if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
@ -1109,6 +1151,9 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1132,6 +1177,9 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint32_t value = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK);
|
||||
else if (adev->powerplay.pp_funcs->get_sclk_od)
|
||||
@ -1150,6 +1198,9 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev,
|
||||
int ret;
|
||||
long int value;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtol(buf, 0, &value);
|
||||
|
||||
if (ret) {
|
||||
@ -1183,6 +1234,9 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint32_t value = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK);
|
||||
else if (adev->powerplay.pp_funcs->get_mclk_od)
|
||||
@ -1201,6 +1255,9 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
|
||||
int ret;
|
||||
long int value;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
ret = kstrtol(buf, 0, &value);
|
||||
|
||||
if (ret) {
|
||||
@ -1253,6 +1310,9 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (is_support_sw_smu(adev))
|
||||
return smu_get_power_profile_mode(&adev->smu, buf);
|
||||
else if (adev->powerplay.pp_funcs->get_power_profile_mode)
|
||||
@ -1285,6 +1345,9 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
|
||||
if (count < 2 || count > 127)
|
||||
return -EINVAL;
|
||||
@ -1331,6 +1394,9 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int r, value, size = sizeof(value);
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* read the IP busy sensor */
|
||||
r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD,
|
||||
(void *)&value, &size);
|
||||
@ -1357,6 +1423,9 @@ static ssize_t amdgpu_get_memory_busy_percent(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int r, value, size = sizeof(value);
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* read the IP busy sensor */
|
||||
r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD,
|
||||
(void *)&value, &size);
|
||||
@ -1387,6 +1456,9 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev,
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint64_t count0, count1;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
amdgpu_asic_get_pcie_usage(adev, &count0, &count1);
|
||||
return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n",
|
||||
count0, count1, pcie_get_mps(adev->pdev));
|
||||
@ -1409,6 +1481,9 @@ static ssize_t amdgpu_get_unique_id(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
if (adev->unique_id)
|
||||
return snprintf(buf, PAGE_SIZE, "%016llx\n", adev->unique_id);
|
||||
|
||||
@ -1603,6 +1678,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev,
|
||||
{
|
||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
u32 pwm_mode = 0;
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
pwm_mode = smu_get_fan_control_mode(&adev->smu);
|
||||
} else {
|
||||
@ -2053,6 +2129,9 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
|
||||
int err;
|
||||
u32 value;
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return -EINVAL;
|
||||
|
||||
err = kstrtou32(buf, 10, &value);
|
||||
if (err)
|
||||
return err;
|
||||
@ -2299,6 +2378,23 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
|
||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
umode_t effective_mode = attr->mode;
|
||||
|
||||
/* under multi-vf mode, the hwmon attributes are all not supported */
|
||||
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* there is no fan under pp one vf mode */
|
||||
if (amdgpu_sriov_is_pp_one_vf(adev) &&
|
||||
(attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_pwm1_min.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_fan1_input.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_fan1_min.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_fan1_max.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_fan1_target.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_fan1_enable.dev_attr.attr))
|
||||
return 0;
|
||||
|
||||
/* Skip fan attributes if fan is not present */
|
||||
if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
|
||||
@ -2718,42 +2814,16 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
|
||||
|
||||
}
|
||||
|
||||
int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev)
|
||||
void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev)))
|
||||
return ret;
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_sclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_sclk\n");
|
||||
return ret;
|
||||
if (is_support_sw_smu(adev)) {
|
||||
ret = smu_dpm_set_power_gate(&adev->smu, AMD_IP_BLOCK_TYPE_JPEG, enable);
|
||||
if (ret)
|
||||
DRM_ERROR("[SW SMU]: dpm enable jpeg failed, state = %s, ret = %d. \n",
|
||||
enable ? "true" : "false", ret);
|
||||
}
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_mclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_mclk\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_create_file(adev->dev, &dev_attr_power_dpm_force_performance_level);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file for dpm state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (!(amdgpu_sriov_vf(adev) && amdgim_is_hwperf(adev)))
|
||||
return;
|
||||
|
||||
device_remove_file(adev->dev, &dev_attr_power_dpm_force_performance_level);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
|
||||
}
|
||||
|
||||
int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
|
||||
|
@ -41,5 +41,6 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev);
|
||||
void amdgpu_dpm_thermal_work_handler(struct work_struct *work);
|
||||
void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable);
|
||||
void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable);
|
||||
void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable);
|
||||
|
||||
#endif
|
||||
|
@ -158,7 +158,7 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
||||
memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
index = atomic_inc_return(&psp->fence_value);
|
||||
ret = psp_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index);
|
||||
ret = psp_ring_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index);
|
||||
if (ret) {
|
||||
atomic_dec(&psp->fence_value);
|
||||
mutex_unlock(&psp->mutex);
|
||||
@ -318,35 +318,17 @@ static int psp_tmr_load(struct psp_context *psp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint64_t asd_mc, uint64_t asd_mc_shared,
|
||||
uint32_t size, uint32_t shared_size)
|
||||
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint64_t asd_mc, uint32_t size)
|
||||
{
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_ASD;
|
||||
cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(asd_mc);
|
||||
cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(asd_mc);
|
||||
cmd->cmd.cmd_load_ta.app_len = size;
|
||||
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(asd_mc_shared);
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(asd_mc_shared);
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size;
|
||||
}
|
||||
|
||||
static int psp_asd_init(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allocate 16k memory aligned to 4k from Frame Buffer (local
|
||||
* physical) for shared ASD <-> Driver
|
||||
*/
|
||||
ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE,
|
||||
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
|
||||
&psp->asd_shared_bo,
|
||||
&psp->asd_shared_mc_addr,
|
||||
&psp->asd_shared_buf);
|
||||
|
||||
return ret;
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = 0;
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = 0;
|
||||
cmd->cmd.cmd_load_ta.cmd_buf_len = 0;
|
||||
}
|
||||
|
||||
static int psp_asd_load(struct psp_context *psp)
|
||||
@ -368,11 +350,49 @@ static int psp_asd_load(struct psp_context *psp)
|
||||
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
|
||||
memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size);
|
||||
|
||||
psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr,
|
||||
psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE);
|
||||
psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr,
|
||||
psp->asd_ucode_size);
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
if (!ret) {
|
||||
psp->asd_context.asd_initialized = true;
|
||||
psp->asd_context.session_id = cmd->resp.session_id;
|
||||
}
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void psp_prep_asd_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd,
|
||||
uint32_t asd_session_id)
|
||||
{
|
||||
cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA;
|
||||
cmd->cmd.cmd_unload_ta.session_id = asd_session_id;
|
||||
}
|
||||
|
||||
static int psp_asd_unload(struct psp_context *psp)
|
||||
{
|
||||
int ret;
|
||||
struct psp_gfx_cmd_resp *cmd;
|
||||
|
||||
if (amdgpu_sriov_vf(psp->adev))
|
||||
return 0;
|
||||
|
||||
if (!psp->asd_context.asd_initialized)
|
||||
return 0;
|
||||
|
||||
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
psp_prep_asd_unload_cmd_buf(cmd, psp->asd_context.session_id);
|
||||
|
||||
ret = psp_cmd_submit_buf(psp, NULL, cmd,
|
||||
psp->fence_buf_mc_addr);
|
||||
if (!ret)
|
||||
psp->asd_context.asd_initialized = false;
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
@ -1211,45 +1231,6 @@ static int psp_hw_start(struct psp_context *psp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_asd_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP asd init failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_asd_load(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP load asd failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
ret = psp_xgmi_initialize(psp);
|
||||
/* Warning the XGMI seesion initialize failure
|
||||
* Instead of stop driver initialization
|
||||
*/
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"XGMI: Failed to initialize XGMI session\n");
|
||||
}
|
||||
|
||||
if (psp->adev->psp.ta_fw) {
|
||||
ret = psp_ras_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"RAS: Failed to initialize RAS\n");
|
||||
|
||||
ret = psp_hdcp_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"HDCP: Failed to initialize HDCP\n");
|
||||
|
||||
ret = psp_dtm_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"DTM: Failed to initialize DTM\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1341,6 +1322,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
|
||||
case AMDGPU_UCODE_ID_VCN1_RAM:
|
||||
*type = GFX_FW_TYPE_VCN1_RAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_DMCUB:
|
||||
*type = GFX_FW_TYPE_DMUB;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -1562,6 +1546,39 @@ skip_memalloc:
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
ret = psp_asd_load(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP load asd failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
ret = psp_xgmi_initialize(psp);
|
||||
/* Warning the XGMI seesion initialize failure
|
||||
* Instead of stop driver initialization
|
||||
*/
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"XGMI: Failed to initialize XGMI session\n");
|
||||
}
|
||||
|
||||
if (psp->adev->psp.ta_fw) {
|
||||
ret = psp_ras_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"RAS: Failed to initialize RAS\n");
|
||||
|
||||
ret = psp_hdcp_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"HDCP: Failed to initialize HDCP\n");
|
||||
|
||||
ret = psp_dtm_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"DTM: Failed to initialize DTM\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
@ -1619,6 +1636,8 @@ static int psp_hw_fini(void *handle)
|
||||
psp_hdcp_terminate(psp);
|
||||
}
|
||||
|
||||
psp_asd_unload(psp);
|
||||
|
||||
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
|
||||
|
||||
pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
|
||||
@ -1627,8 +1646,6 @@ static int psp_hw_fini(void *handle)
|
||||
&psp->fw_pri_mc_addr, &psp->fw_pri_buf);
|
||||
amdgpu_bo_free_kernel(&psp->fence_buf_bo,
|
||||
&psp->fence_buf_mc_addr, &psp->fence_buf);
|
||||
amdgpu_bo_free_kernel(&psp->asd_shared_bo, &psp->asd_shared_mc_addr,
|
||||
&psp->asd_shared_buf);
|
||||
amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
|
||||
(void **)&psp->cmd_buf_mem);
|
||||
|
||||
@ -1704,6 +1721,39 @@ static int psp_resume(void *handle)
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
ret = psp_asd_load(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP load asd failed!\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
ret = psp_xgmi_initialize(psp);
|
||||
/* Warning the XGMI seesion initialize failure
|
||||
* Instead of stop driver initialization
|
||||
*/
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"XGMI: Failed to initialize XGMI session\n");
|
||||
}
|
||||
|
||||
if (psp->adev->psp.ta_fw) {
|
||||
ret = psp_ras_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"RAS: Failed to initialize RAS\n");
|
||||
|
||||
ret = psp_hdcp_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"HDCP: Failed to initialize HDCP\n");
|
||||
|
||||
ret = psp_dtm_initialize(psp);
|
||||
if (ret)
|
||||
dev_err(psp->adev->dev,
|
||||
"DTM: Failed to initialize DTM\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&adev->firmware.mutex);
|
||||
|
||||
return 0;
|
||||
@ -1758,6 +1808,56 @@ int psp_update_vcn_sram(struct amdgpu_device *adev, int inst_idx,
|
||||
return psp_execute_np_fw_load(&adev->psp, &ucode);
|
||||
}
|
||||
|
||||
int psp_ring_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr,
|
||||
uint64_t fence_mc_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int psp_write_ptr_reg = 0;
|
||||
struct psp_gfx_rb_frame *write_frame;
|
||||
struct psp_ring *ring = &psp->km_ring;
|
||||
struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
|
||||
struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
|
||||
ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
uint32_t ring_size_dw = ring->ring_size / 4;
|
||||
uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
|
||||
|
||||
/* KM (GPCOM) prepare write pointer */
|
||||
psp_write_ptr_reg = psp_ring_get_wptr(psp);
|
||||
|
||||
/* Update KM RB frame pointer to new frame */
|
||||
/* write_frame ptr increments by size of rb_frame in bytes */
|
||||
/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
|
||||
if ((psp_write_ptr_reg % ring_size_dw) == 0)
|
||||
write_frame = ring_buffer_start;
|
||||
else
|
||||
write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
|
||||
/* Check invalid write_frame ptr address */
|
||||
if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
|
||||
DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
|
||||
ring_buffer_start, ring_buffer_end, write_frame);
|
||||
DRM_ERROR("write_frame is pointing to address out of bounds\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize KM RB frame */
|
||||
memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
|
||||
|
||||
/* Update KM RB frame */
|
||||
write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
|
||||
write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
|
||||
write_frame->fence_value = index;
|
||||
amdgpu_asic_flush_hdp(adev, NULL);
|
||||
|
||||
/* Update the write Pointer in DWORDs */
|
||||
psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
|
||||
psp_ring_set_wptr(psp, psp_write_ptr_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool psp_check_fw_loading_status(struct amdgpu_device *adev,
|
||||
enum AMDGPU_UCODE_ID ucode_type)
|
||||
{
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#define PSP_FENCE_BUFFER_SIZE 0x1000
|
||||
#define PSP_CMD_BUFFER_SIZE 0x1000
|
||||
#define PSP_ASD_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_XGMI_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_RAS_SHARED_MEM_SIZE 0x4000
|
||||
#define PSP_1_MEG 0x100000
|
||||
@ -94,9 +93,6 @@ struct psp_funcs
|
||||
enum psp_ring_type ring_type);
|
||||
int (*ring_destroy)(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type);
|
||||
int (*cmd_submit)(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
|
||||
int index);
|
||||
bool (*compare_sram_data)(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info *ucode,
|
||||
enum AMDGPU_UCODE_ID ucode_type);
|
||||
@ -116,6 +112,8 @@ struct psp_funcs
|
||||
int (*mem_training_init)(struct psp_context *psp);
|
||||
void (*mem_training_fini)(struct psp_context *psp);
|
||||
int (*mem_training)(struct psp_context *psp, uint32_t ops);
|
||||
uint32_t (*ring_get_wptr)(struct psp_context *psp);
|
||||
void (*ring_set_wptr)(struct psp_context *psp, uint32_t value);
|
||||
};
|
||||
|
||||
#define AMDGPU_XGMI_MAX_CONNECTED_NODES 64
|
||||
@ -131,6 +129,11 @@ struct psp_xgmi_topology_info {
|
||||
struct psp_xgmi_node_info nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES];
|
||||
};
|
||||
|
||||
struct psp_asd_context {
|
||||
bool asd_initialized;
|
||||
uint32_t session_id;
|
||||
};
|
||||
|
||||
struct psp_xgmi_context {
|
||||
uint8_t initialized;
|
||||
uint32_t session_id;
|
||||
@ -239,15 +242,12 @@ struct psp_context
|
||||
struct amdgpu_bo *tmr_bo;
|
||||
uint64_t tmr_mc_addr;
|
||||
|
||||
/* asd firmware and buffer */
|
||||
/* asd firmware */
|
||||
const struct firmware *asd_fw;
|
||||
uint32_t asd_fw_version;
|
||||
uint32_t asd_feature_version;
|
||||
uint32_t asd_ucode_size;
|
||||
uint8_t *asd_start_addr;
|
||||
struct amdgpu_bo *asd_shared_bo;
|
||||
uint64_t asd_shared_mc_addr;
|
||||
void *asd_shared_buf;
|
||||
|
||||
/* fence buffer */
|
||||
struct amdgpu_bo *fence_buf_bo;
|
||||
@ -282,6 +282,7 @@ struct psp_context
|
||||
uint32_t ta_dtm_ucode_size;
|
||||
uint8_t *ta_dtm_start_addr;
|
||||
|
||||
struct psp_asd_context asd_context;
|
||||
struct psp_xgmi_context xgmi_context;
|
||||
struct psp_ras_context ras;
|
||||
struct psp_hdcp_context hdcp_context;
|
||||
@ -300,8 +301,6 @@ struct amdgpu_psp_funcs {
|
||||
#define psp_ring_create(psp, type) (psp)->funcs->ring_create((psp), (type))
|
||||
#define psp_ring_stop(psp, type) (psp)->funcs->ring_stop((psp), (type))
|
||||
#define psp_ring_destroy(psp, type) ((psp)->funcs->ring_destroy((psp), (type)))
|
||||
#define psp_cmd_submit(psp, cmd_mc, fence_mc, index) \
|
||||
(psp)->funcs->cmd_submit((psp), (cmd_mc), (fence_mc), (index))
|
||||
#define psp_compare_sram_data(psp, ucode, type) \
|
||||
(psp)->funcs->compare_sram_data((psp), (ucode), (type))
|
||||
#define psp_init_microcode(psp) \
|
||||
@ -346,6 +345,9 @@ struct amdgpu_psp_funcs {
|
||||
((psp)->funcs->ras_cure_posion ? \
|
||||
(psp)->funcs->ras_cure_posion(psp, (addr)) : -EINVAL)
|
||||
|
||||
#define psp_ring_get_wptr(psp) (psp)->funcs->ring_get_wptr((psp))
|
||||
#define psp_ring_set_wptr(psp, value) (psp)->funcs->ring_set_wptr((psp), (value))
|
||||
|
||||
extern const struct amd_ip_funcs psp_ip_funcs;
|
||||
|
||||
extern const struct amdgpu_ip_block_version psp_v3_1_ip_block;
|
||||
@ -372,4 +374,8 @@ int psp_rlc_autoload_start(struct psp_context *psp);
|
||||
extern const struct amdgpu_ip_block_version psp_v11_0_ip_block;
|
||||
int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,
|
||||
uint32_t value);
|
||||
int psp_ring_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr,
|
||||
uint64_t fence_mc_addr,
|
||||
int index);
|
||||
#endif
|
||||
|
@ -198,9 +198,6 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head);
|
||||
|
||||
/**
|
||||
* DOC: AMDGPU RAS debugfs control interface
|
||||
*
|
||||
@ -445,7 +442,7 @@ static struct ras_manager *amdgpu_ras_create_obj(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
/* return an obj equal to head, or the first when head is NULL */
|
||||
static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
|
||||
struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head)
|
||||
{
|
||||
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
||||
@ -1687,7 +1684,8 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev,
|
||||
*supported = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) ||
|
||||
adev->asic_type != CHIP_VEGA20)
|
||||
(adev->asic_type != CHIP_VEGA20 &&
|
||||
adev->asic_type != CHIP_ARCTURUS))
|
||||
return;
|
||||
|
||||
if (adev->is_atom_fw &&
|
||||
|
@ -611,6 +611,9 @@ int amdgpu_ras_interrupt_remove_handler(struct amdgpu_device *adev,
|
||||
int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
|
||||
struct ras_dispatch_if *info);
|
||||
|
||||
struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
|
||||
struct ras_common_if *head);
|
||||
|
||||
extern atomic_t amdgpu_ras_in_intr;
|
||||
|
||||
static inline bool amdgpu_ras_intr_triggered(void)
|
||||
@ -618,6 +621,11 @@ static inline bool amdgpu_ras_intr_triggered(void)
|
||||
return !!atomic_read(&amdgpu_ras_in_intr);
|
||||
}
|
||||
|
||||
static inline void amdgpu_ras_intr_cleared(void)
|
||||
{
|
||||
atomic_set(&amdgpu_ras_in_intr, 0);
|
||||
}
|
||||
|
||||
void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
@ -129,7 +129,8 @@ static void amdgpu_sync_keep_later(struct dma_fence **keep,
|
||||
* Tries to add the fence to an existing hash entry. Returns true when an entry
|
||||
* was found, false otherwise.
|
||||
*/
|
||||
static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f, bool explicit)
|
||||
static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f,
|
||||
bool explicit)
|
||||
{
|
||||
struct amdgpu_sync_entry *e;
|
||||
|
||||
@ -151,19 +152,18 @@ static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f,
|
||||
* amdgpu_sync_fence - remember to sync to this fence
|
||||
*
|
||||
* @sync: sync object to add fence to
|
||||
* @fence: fence to sync to
|
||||
* @f: fence to sync to
|
||||
* @explicit: if this is an explicit dependency
|
||||
*
|
||||
* Add the fence to the sync object.
|
||||
*/
|
||||
int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
||||
struct dma_fence *f, bool explicit)
|
||||
int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f,
|
||||
bool explicit)
|
||||
{
|
||||
struct amdgpu_sync_entry *e;
|
||||
|
||||
if (!f)
|
||||
return 0;
|
||||
if (amdgpu_sync_same_dev(adev, f) &&
|
||||
amdgpu_sync_get_owner(f) == AMDGPU_FENCE_OWNER_VM)
|
||||
amdgpu_sync_keep_later(&sync->last_vm_update, f);
|
||||
|
||||
if (amdgpu_sync_add_later(sync, f, explicit))
|
||||
return 0;
|
||||
@ -179,6 +179,24 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_sync_vm_fence - remember to sync to this VM fence
|
||||
*
|
||||
* @adev: amdgpu device
|
||||
* @sync: sync object to add fence to
|
||||
* @fence: the VM fence to add
|
||||
*
|
||||
* Add the fence to the sync object and remember it as VM update.
|
||||
*/
|
||||
int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence)
|
||||
{
|
||||
if (!fence)
|
||||
return 0;
|
||||
|
||||
amdgpu_sync_keep_later(&sync->last_vm_update, fence);
|
||||
return amdgpu_sync_fence(sync, fence, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_sync_resv - sync to a reservation object
|
||||
*
|
||||
@ -204,7 +222,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
|
||||
|
||||
/* always sync to the exclusive fence */
|
||||
f = dma_resv_get_excl(resv);
|
||||
r = amdgpu_sync_fence(adev, sync, f, false);
|
||||
r = amdgpu_sync_fence(sync, f, false);
|
||||
|
||||
flist = dma_resv_get_list(resv);
|
||||
if (!flist || r)
|
||||
@ -222,13 +240,11 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
|
||||
continue;
|
||||
|
||||
if (amdgpu_sync_same_dev(adev, f)) {
|
||||
/* VM updates are only interesting
|
||||
* for other VM updates and moves.
|
||||
/* VM updates only sync with moves but not with user
|
||||
* command submissions or KFD evictions fences
|
||||
*/
|
||||
if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
|
||||
(fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
|
||||
((owner == AMDGPU_FENCE_OWNER_VM) !=
|
||||
(fence_owner == AMDGPU_FENCE_OWNER_VM)))
|
||||
if (owner == AMDGPU_FENCE_OWNER_VM &&
|
||||
fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED)
|
||||
continue;
|
||||
|
||||
/* Ignore fence from the same owner and explicit one as
|
||||
@ -239,7 +255,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
|
||||
continue;
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(adev, sync, f, false);
|
||||
r = amdgpu_sync_fence(sync, f, false);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
@ -340,7 +356,7 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone)
|
||||
hash_for_each_safe(source->fences, i, tmp, e, node) {
|
||||
f = e->fence;
|
||||
if (!dma_fence_is_signaled(f)) {
|
||||
r = amdgpu_sync_fence(NULL, clone, f, e->explicit);
|
||||
r = amdgpu_sync_fence(clone, f, e->explicit);
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
|
@ -40,8 +40,9 @@ struct amdgpu_sync {
|
||||
};
|
||||
|
||||
void amdgpu_sync_create(struct amdgpu_sync *sync);
|
||||
int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
|
||||
struct dma_fence *f, bool explicit);
|
||||
int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f,
|
||||
bool explicit);
|
||||
int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence);
|
||||
int amdgpu_sync_resv(struct amdgpu_device *adev,
|
||||
struct amdgpu_sync *sync,
|
||||
struct dma_resv *resv,
|
||||
@ -49,7 +50,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
|
||||
bool explicit_sync);
|
||||
struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
|
||||
struct amdgpu_ring *ring);
|
||||
struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync, bool *explicit);
|
||||
struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync,
|
||||
bool *explicit);
|
||||
int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone);
|
||||
int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr);
|
||||
void amdgpu_sync_free(struct amdgpu_sync *sync);
|
||||
|
@ -1522,11 +1522,8 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
|
||||
struct dma_fence *f;
|
||||
int i;
|
||||
|
||||
/* Don't evict VM page tables while they are busy, otherwise we can't
|
||||
* cleanly handle page faults.
|
||||
*/
|
||||
if (bo->type == ttm_bo_type_kernel &&
|
||||
!dma_resv_test_signaled_rcu(bo->base.resv, true))
|
||||
!amdgpu_vm_evictable(ttm_to_amdgpu_bo(bo)))
|
||||
return false;
|
||||
|
||||
/* If bo is a KFD BO, check if the bo belongs to the current process.
|
||||
|
@ -447,6 +447,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
|
||||
const struct common_firmware_header *header = NULL;
|
||||
const struct gfx_firmware_header_v1_0 *cp_hdr = NULL;
|
||||
const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL;
|
||||
const struct dmcub_firmware_header_v1_0 *dmcub_hdr = NULL;
|
||||
|
||||
if (NULL == ucode->fw)
|
||||
return 0;
|
||||
@ -460,6 +461,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
|
||||
header = (const struct common_firmware_header *)ucode->fw->data;
|
||||
cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
|
||||
dmcu_hdr = (const struct dmcu_firmware_header_v1_0 *)ucode->fw->data;
|
||||
dmcub_hdr = (const struct dmcub_firmware_header_v1_0 *)ucode->fw->data;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP ||
|
||||
(ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 &&
|
||||
@ -470,7 +472,8 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM &&
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM &&
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM &&
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV)) {
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV &&
|
||||
ucode->ucode_id != AMDGPU_UCODE_ID_DMCUB)) {
|
||||
ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes);
|
||||
|
||||
memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
|
||||
@ -506,6 +509,12 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev,
|
||||
le32_to_cpu(header->ucode_array_offset_bytes) +
|
||||
le32_to_cpu(dmcu_hdr->intv_offset_bytes)),
|
||||
ucode->ucode_size);
|
||||
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCUB) {
|
||||
ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes);
|
||||
memcpy(ucode->kaddr,
|
||||
(void *)((uint8_t *)ucode->fw->data +
|
||||
le32_to_cpu(header->ucode_array_offset_bytes)),
|
||||
ucode->ucode_size);
|
||||
} else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) {
|
||||
ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes;
|
||||
memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl,
|
||||
|
@ -251,6 +251,13 @@ struct dmcu_firmware_header_v1_0 {
|
||||
uint32_t intv_size_bytes; /* size of interrupt vectors, in bytes */
|
||||
};
|
||||
|
||||
/* version_major=1, version_minor=0 */
|
||||
struct dmcub_firmware_header_v1_0 {
|
||||
struct common_firmware_header header;
|
||||
uint32_t inst_const_bytes; /* size of instruction region, in bytes */
|
||||
uint32_t bss_data_bytes; /* size of bss/data region, in bytes */
|
||||
};
|
||||
|
||||
/* header is fixed size */
|
||||
union amdgpu_firmware_header {
|
||||
struct common_firmware_header common;
|
||||
@ -268,6 +275,7 @@ union amdgpu_firmware_header {
|
||||
struct sdma_firmware_header_v1_1 sdma_v1_1;
|
||||
struct gpu_info_firmware_header_v1_0 gpu_info;
|
||||
struct dmcu_firmware_header_v1_0 dmcu;
|
||||
struct dmcub_firmware_header_v1_0 dmcub;
|
||||
uint8_t raw[0x100];
|
||||
};
|
||||
|
||||
@ -307,6 +315,7 @@ enum AMDGPU_UCODE_ID {
|
||||
AMDGPU_UCODE_ID_DMCU_INTV,
|
||||
AMDGPU_UCODE_ID_VCN0_RAM,
|
||||
AMDGPU_UCODE_ID_VCN1_RAM,
|
||||
AMDGPU_UCODE_ID_DMCUB,
|
||||
AMDGPU_UCODE_ID_MAXIMUM,
|
||||
};
|
||||
|
||||
|
@ -349,6 +349,7 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
|
||||
unsigned size;
|
||||
void *ptr;
|
||||
int i, j;
|
||||
bool in_ras_intr = amdgpu_ras_intr_triggered();
|
||||
|
||||
cancel_delayed_work_sync(&adev->uvd.idle_work);
|
||||
|
||||
@ -376,13 +377,15 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* re-write 0 since err_event_athub will corrupt VCPU buffer */
|
||||
if (amdgpu_ras_intr_triggered()) {
|
||||
DRM_WARN("UVD VCPU state may lost due to RAS ERREVENT_ATHUB_INTERRUPT\n");
|
||||
if (in_ras_intr)
|
||||
memset(adev->uvd.inst[j].saved_bo, 0, size);
|
||||
} else {
|
||||
else
|
||||
memcpy_fromio(adev->uvd.inst[j].saved_bo, ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_ras_intr)
|
||||
DRM_WARN("UVD VCPU state may lost due to RAS ERREVENT_ATHUB_INTERRUPT\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,8 +214,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
|
||||
|
||||
for (i = 0; i < adev->vcn.num_enc_rings; ++i)
|
||||
amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
|
||||
|
||||
amdgpu_ring_fini(&adev->vcn.inst[j].ring_jpeg);
|
||||
}
|
||||
|
||||
release_firmware(adev->vcn.fw);
|
||||
@ -308,7 +306,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
else
|
||||
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
|
||||
|
||||
if (amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_jpeg))
|
||||
if (amdgpu_fence_count_emitted(&adev->jpeg.inst[j].ring_dec))
|
||||
new_state.jpeg = VCN_DPG_STATE__PAUSE;
|
||||
else
|
||||
new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
|
||||
@ -316,7 +314,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
adev->vcn.pause_dpg_mode(adev, &new_state);
|
||||
}
|
||||
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_jpeg);
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->jpeg.inst[j].ring_dec);
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
|
||||
fences += fence[j];
|
||||
}
|
||||
@ -360,7 +358,7 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
else
|
||||
new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
|
||||
|
||||
if (amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_jpeg))
|
||||
if (amdgpu_fence_count_emitted(&adev->jpeg.inst[ring->me].ring_dec))
|
||||
new_state.jpeg = VCN_DPG_STATE__PAUSE;
|
||||
else
|
||||
new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
|
||||
@ -708,108 +706,3 @@ error:
|
||||
amdgpu_bo_unref(&bo);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_jpeg_ring_test_ring(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
WREG32(adev->vcn.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD);
|
||||
r = amdgpu_ring_alloc(ring, 3);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.jpeg_pitch, 0));
|
||||
amdgpu_ring_write(ring, 0xDEADBEEF);
|
||||
amdgpu_ring_commit(ring);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(adev->vcn.inst[ring->me].external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_vcn_jpeg_set_reg(struct amdgpu_ring *ring, uint32_t handle,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct dma_fence *f = NULL;
|
||||
const unsigned ib_size_dw = 16;
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ib = &job->ibs[0];
|
||||
|
||||
ib->ptr[0] = PACKETJ(adev->vcn.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0);
|
||||
ib->ptr[1] = 0xDEADBEEF;
|
||||
for (i = 2; i < 16; i += 2) {
|
||||
ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
ib->ptr[i+1] = 0;
|
||||
}
|
||||
ib->length_dw = 16;
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (fence)
|
||||
*fence = dma_fence_get(f);
|
||||
dma_fence_put(f);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
amdgpu_job_free(job);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_vcn_jpeg_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
struct dma_fence *fence = NULL;
|
||||
long r = 0;
|
||||
|
||||
r = amdgpu_vcn_jpeg_set_reg(ring, 1, &fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
r = dma_fence_wait_timeout(fence, false, timeout);
|
||||
if (r == 0) {
|
||||
r = -ETIMEDOUT;
|
||||
goto error;
|
||||
} else if (r < 0) {
|
||||
goto error;
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(adev->vcn.inst[ring->me].external.jpeg_pitch);
|
||||
if (tmp == 0xDEADBEEF)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
r = -ETIMEDOUT;
|
||||
|
||||
dma_fence_put(fence);
|
||||
error:
|
||||
return r;
|
||||
}
|
||||
|
@ -158,7 +158,6 @@ struct amdgpu_vcn_reg{
|
||||
unsigned ib_size;
|
||||
unsigned gp_scratch8;
|
||||
unsigned scratch9;
|
||||
unsigned jpeg_pitch;
|
||||
};
|
||||
|
||||
struct amdgpu_vcn_inst {
|
||||
@ -168,7 +167,6 @@ struct amdgpu_vcn_inst {
|
||||
void *saved_bo;
|
||||
struct amdgpu_ring ring_dec;
|
||||
struct amdgpu_ring ring_enc[AMDGPU_VCN_MAX_ENC_RINGS];
|
||||
struct amdgpu_ring ring_jpeg;
|
||||
struct amdgpu_irq_src irq;
|
||||
struct amdgpu_vcn_reg external;
|
||||
};
|
||||
@ -209,7 +207,4 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
|
||||
int amdgpu_vcn_jpeg_ring_test_ring(struct amdgpu_ring *ring);
|
||||
int amdgpu_vcn_jpeg_ring_test_ib(struct amdgpu_ring *ring, long timeout);
|
||||
|
||||
#endif
|
||||
|
@ -379,54 +379,3 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t parse_clk(char *buf, bool min)
|
||||
{
|
||||
char *ptr = buf;
|
||||
uint32_t clk = 0;
|
||||
|
||||
do {
|
||||
ptr = strchr(ptr, ':');
|
||||
if (!ptr)
|
||||
break;
|
||||
ptr+=2;
|
||||
if (kstrtou32(ptr, 10, &clk))
|
||||
return 0;
|
||||
} while (!min);
|
||||
|
||||
return clk * 100;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_virt_get_sclk(struct amdgpu_device *adev, bool lowest)
|
||||
{
|
||||
char *buf = NULL;
|
||||
uint32_t clk = 0;
|
||||
|
||||
buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->virt.ops->get_pp_clk(adev, PP_SCLK, buf);
|
||||
clk = parse_clk(buf, lowest);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
uint32_t amdgpu_virt_get_mclk(struct amdgpu_device *adev, bool lowest)
|
||||
{
|
||||
char *buf = NULL;
|
||||
uint32_t clk = 0;
|
||||
|
||||
buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
adev->virt.ops->get_pp_clk(adev, PP_MCLK, buf);
|
||||
clk = parse_clk(buf, lowest);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
@ -57,8 +57,6 @@ struct amdgpu_virt_ops {
|
||||
int (*reset_gpu)(struct amdgpu_device *adev);
|
||||
int (*wait_reset)(struct amdgpu_device *adev);
|
||||
void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3);
|
||||
int (*get_pp_clk)(struct amdgpu_device *adev, u32 type, char *buf);
|
||||
int (*force_dpm_level)(struct amdgpu_device *adev, u32 level);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -85,8 +83,8 @@ enum AMDGIM_FEATURE_FLAG {
|
||||
AMDGIM_FEATURE_GIM_LOAD_UCODES = 0x2,
|
||||
/* VRAM LOST by GIM */
|
||||
AMDGIM_FEATURE_GIM_FLR_VRAMLOST = 0x4,
|
||||
/* HW PERF SIM in GIM */
|
||||
AMDGIM_FEATURE_HW_PERF_SIMULATION = (1 << 3),
|
||||
/* PP ONE VF MODE in GIM */
|
||||
AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),
|
||||
};
|
||||
|
||||
struct amd_sriov_msg_pf2vf_info_header {
|
||||
@ -257,8 +255,6 @@ struct amdgpu_virt {
|
||||
struct amdgpu_vf_error_buffer vf_errors;
|
||||
struct amdgpu_virt_fw_reserve fw_reserve;
|
||||
uint32_t gim_feature;
|
||||
/* protect DPM events to GIM */
|
||||
struct mutex dpm_mutex;
|
||||
uint32_t reg_access_mode;
|
||||
};
|
||||
|
||||
@ -286,8 +282,8 @@ static inline bool is_virtual_machine(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#define amdgim_is_hwperf(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_HW_PERF_SIMULATION)
|
||||
#define amdgpu_sriov_is_pp_one_vf(adev) \
|
||||
((adev)->virt.gim_feature & AMDGIM_FEATURE_PP_ONE_VF)
|
||||
|
||||
bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
|
||||
void amdgpu_virt_init_setting(struct amdgpu_device *adev);
|
||||
@ -306,6 +302,4 @@ int amdgpu_virt_fw_reserve_get_checksum(void *obj, unsigned long obj_size,
|
||||
unsigned int key,
|
||||
unsigned int chksum);
|
||||
void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev);
|
||||
uint32_t amdgpu_virt_get_sclk(struct amdgpu_device *adev, bool lowest);
|
||||
uint32_t amdgpu_virt_get_mclk(struct amdgpu_device *adev, bool lowest);
|
||||
#endif
|
||||
|
@ -562,8 +562,8 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
|
||||
{
|
||||
entry->priority = 0;
|
||||
entry->tv.bo = &vm->root.base.bo->tbo;
|
||||
/* One for the VM updates, one for TTM and one for the CS job */
|
||||
entry->tv.num_shared = 3;
|
||||
/* One for TTM and one for the CS job */
|
||||
entry->tv.num_shared = 2;
|
||||
entry->user_pages = NULL;
|
||||
list_add(&entry->tv.head, validated);
|
||||
}
|
||||
@ -656,7 +656,7 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
void *param)
|
||||
{
|
||||
struct amdgpu_vm_bo_base *bo_base, *tmp;
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
vm->bulk_moveable &= list_empty(&vm->evicted);
|
||||
|
||||
@ -665,7 +665,7 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
|
||||
r = validate(param, bo);
|
||||
if (r)
|
||||
break;
|
||||
return r;
|
||||
|
||||
if (bo->tbo.type != ttm_bo_type_kernel) {
|
||||
amdgpu_vm_bo_moved(bo_base);
|
||||
@ -678,7 +678,11 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
mutex_lock(&vm->eviction_lock);
|
||||
vm->evicting = false;
|
||||
mutex_unlock(&vm->eviction_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1555,15 +1559,25 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
|
||||
if (!(flags & AMDGPU_PTE_VALID))
|
||||
owner = AMDGPU_FENCE_OWNER_KFD;
|
||||
|
||||
mutex_lock(&vm->eviction_lock);
|
||||
if (vm->evicting) {
|
||||
r = -EBUSY;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
r = vm->update_funcs->prepare(¶ms, owner, exclusive);
|
||||
if (r)
|
||||
return r;
|
||||
goto error_unlock;
|
||||
|
||||
r = amdgpu_vm_update_ptes(¶ms, start, last + 1, addr, flags);
|
||||
if (r)
|
||||
return r;
|
||||
goto error_unlock;
|
||||
|
||||
return vm->update_funcs->commit(¶ms, fence);
|
||||
r = vm->update_funcs->commit(¶ms, fence);
|
||||
|
||||
error_unlock:
|
||||
mutex_unlock(&vm->eviction_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2499,6 +2513,41 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
kfree(bo_va);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_evictable - check if we can evict a VM
|
||||
*
|
||||
* @bo: A page table of the VM.
|
||||
*
|
||||
* Check if it is possible to evict a VM.
|
||||
*/
|
||||
bool amdgpu_vm_evictable(struct amdgpu_bo *bo)
|
||||
{
|
||||
struct amdgpu_vm_bo_base *bo_base = bo->vm_bo;
|
||||
|
||||
/* Page tables of a destroyed VM can go away immediately */
|
||||
if (!bo_base || !bo_base->vm)
|
||||
return true;
|
||||
|
||||
/* Don't evict VM page tables while they are busy */
|
||||
if (!dma_resv_test_signaled_rcu(bo->tbo.base.resv, true))
|
||||
return false;
|
||||
|
||||
/* Try to block ongoing updates */
|
||||
if (!mutex_trylock(&bo_base->vm->eviction_lock))
|
||||
return false;
|
||||
|
||||
/* Don't evict VM page tables while they are updated */
|
||||
if (!dma_fence_is_signaled(bo_base->vm->last_direct) ||
|
||||
!dma_fence_is_signaled(bo_base->vm->last_delayed)) {
|
||||
mutex_unlock(&bo_base->vm->eviction_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
bo_base->vm->evicting = true;
|
||||
mutex_unlock(&bo_base->vm->eviction_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_bo_invalidate - mark the bo as invalid
|
||||
*
|
||||
@ -2661,8 +2710,16 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
|
||||
*/
|
||||
long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
|
||||
{
|
||||
return dma_resv_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv,
|
||||
true, true, timeout);
|
||||
timeout = dma_resv_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv,
|
||||
true, true, timeout);
|
||||
if (timeout <= 0)
|
||||
return timeout;
|
||||
|
||||
timeout = dma_fence_wait_timeout(vm->last_direct, true, timeout);
|
||||
if (timeout <= 0)
|
||||
return timeout;
|
||||
|
||||
return dma_fence_wait_timeout(vm->last_delayed, true, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2708,6 +2765,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
goto error_free_direct;
|
||||
|
||||
vm->pte_support_ats = false;
|
||||
vm->is_compute_context = false;
|
||||
|
||||
if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE) {
|
||||
vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
|
||||
@ -2730,6 +2788,11 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
else
|
||||
vm->update_funcs = &amdgpu_vm_sdma_funcs;
|
||||
vm->last_update = NULL;
|
||||
vm->last_direct = dma_fence_get_stub();
|
||||
vm->last_delayed = dma_fence_get_stub();
|
||||
|
||||
mutex_init(&vm->eviction_lock);
|
||||
vm->evicting = false;
|
||||
|
||||
amdgpu_vm_bo_param(adev, vm, adev->vm_manager.root_level, false, &bp);
|
||||
if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE)
|
||||
@ -2780,6 +2843,8 @@ error_free_root:
|
||||
vm->root.base.bo = NULL;
|
||||
|
||||
error_free_delayed:
|
||||
dma_fence_put(vm->last_direct);
|
||||
dma_fence_put(vm->last_delayed);
|
||||
drm_sched_entity_destroy(&vm->delayed);
|
||||
|
||||
error_free_direct:
|
||||
@ -2893,6 +2958,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
vm->update_funcs = &amdgpu_vm_sdma_funcs;
|
||||
dma_fence_put(vm->last_update);
|
||||
vm->last_update = NULL;
|
||||
vm->is_compute_context = true;
|
||||
|
||||
if (vm->pasid) {
|
||||
unsigned long flags;
|
||||
@ -2947,6 +3013,7 @@ void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
||||
spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
|
||||
}
|
||||
vm->pasid = 0;
|
||||
vm->is_compute_context = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2978,6 +3045,11 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
||||
vm->pasid = 0;
|
||||
}
|
||||
|
||||
dma_fence_wait(vm->last_direct, false);
|
||||
dma_fence_put(vm->last_direct);
|
||||
dma_fence_wait(vm->last_delayed, false);
|
||||
dma_fence_put(vm->last_delayed);
|
||||
|
||||
list_for_each_entry_safe(mapping, tmp, &vm->freed, list) {
|
||||
if (mapping->flags & AMDGPU_PTE_PRT && prt_fini_needed) {
|
||||
amdgpu_vm_prt_fini(adev, vm);
|
||||
@ -3194,11 +3266,20 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, unsigned int pasid,
|
||||
flags = AMDGPU_PTE_VALID | AMDGPU_PTE_SNOOPED |
|
||||
AMDGPU_PTE_SYSTEM;
|
||||
|
||||
if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_NEVER) {
|
||||
if (vm->is_compute_context) {
|
||||
/* Intentionally setting invalid PTE flag
|
||||
* combination to force a no-retry-fault
|
||||
*/
|
||||
flags = AMDGPU_PTE_EXECUTABLE | AMDGPU_PDE_PTE |
|
||||
AMDGPU_PTE_TF;
|
||||
value = 0;
|
||||
|
||||
} else if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_NEVER) {
|
||||
/* Redirect the access to the dummy page */
|
||||
value = adev->dummy_page_addr;
|
||||
flags |= AMDGPU_PTE_EXECUTABLE | AMDGPU_PTE_READABLE |
|
||||
AMDGPU_PTE_WRITEABLE;
|
||||
|
||||
} else {
|
||||
/* Let the hw retry silently on the PTE */
|
||||
value = 0;
|
||||
|
@ -239,6 +239,10 @@ struct amdgpu_vm {
|
||||
/* tree of virtual addresses mapped */
|
||||
struct rb_root_cached va;
|
||||
|
||||
/* Lock to prevent eviction while we are updating page tables */
|
||||
struct mutex eviction_lock;
|
||||
bool evicting;
|
||||
|
||||
/* BOs who needs a validation */
|
||||
struct list_head evicted;
|
||||
|
||||
@ -266,6 +270,10 @@ struct amdgpu_vm {
|
||||
struct drm_sched_entity direct;
|
||||
struct drm_sched_entity delayed;
|
||||
|
||||
/* Last submission to the scheduler entities */
|
||||
struct dma_fence *last_direct;
|
||||
struct dma_fence *last_delayed;
|
||||
|
||||
unsigned int pasid;
|
||||
/* dedicated to vm */
|
||||
struct amdgpu_vmid *reserved_vmid[AMDGPU_MAX_VMHUBS];
|
||||
@ -298,6 +306,8 @@ struct amdgpu_vm {
|
||||
struct ttm_lru_bulk_move lru_bulk_move;
|
||||
/* mark whether can do the bulk move */
|
||||
bool bulk_moveable;
|
||||
/* Flag to indicate if VM is used for compute */
|
||||
bool is_compute_context;
|
||||
};
|
||||
|
||||
struct amdgpu_vm_manager {
|
||||
@ -376,6 +386,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
|
||||
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
bool clear);
|
||||
bool amdgpu_vm_evictable(struct amdgpu_bo *bo);
|
||||
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo, bool evicted);
|
||||
uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
|
||||
|
@ -71,7 +71,7 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
|
||||
p->num_dw_left = ndw;
|
||||
|
||||
/* Wait for moves to be completed */
|
||||
r = amdgpu_sync_fence(p->adev, &p->job->sync, exclusive, false);
|
||||
r = amdgpu_sync_fence(&p->job->sync, exclusive, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -95,11 +95,10 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
|
||||
static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
struct amdgpu_bo *root = p->vm->root.base.bo;
|
||||
struct amdgpu_ib *ib = p->job->ibs;
|
||||
struct drm_sched_entity *entity;
|
||||
struct dma_fence *f, *tmp;
|
||||
struct amdgpu_ring *ring;
|
||||
struct dma_fence *f;
|
||||
int r;
|
||||
|
||||
entity = p->direct ? &p->vm->direct : &p->vm->delayed;
|
||||
@ -112,7 +111,13 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
amdgpu_bo_fence(root, f, true);
|
||||
tmp = dma_fence_get(f);
|
||||
if (p->direct)
|
||||
swap(p->vm->last_direct, tmp);
|
||||
else
|
||||
swap(p->vm->last_delayed, tmp);
|
||||
dma_fence_put(tmp);
|
||||
|
||||
if (fence && !p->direct)
|
||||
swap(*fence, f);
|
||||
dma_fence_put(f);
|
||||
|
@ -361,7 +361,6 @@ int amdgpu_atombios_dp_get_panel_mode(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
struct amdgpu_connector_atom_dig *dig_connector;
|
||||
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
|
||||
u16 dp_bridge = amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector);
|
||||
u8 tmp;
|
||||
@ -369,8 +368,6 @@ int amdgpu_atombios_dp_get_panel_mode(struct drm_encoder *encoder,
|
||||
if (!amdgpu_connector->con_priv)
|
||||
return panel_mode;
|
||||
|
||||
dig_connector = amdgpu_connector->con_priv;
|
||||
|
||||
if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
|
||||
/* DP bridge chips */
|
||||
if (drm_dp_dpcd_readb(&amdgpu_connector->ddc_bus->aux,
|
||||
@ -713,7 +710,6 @@ void amdgpu_atombios_dp_link_train(struct drm_encoder *encoder,
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
|
||||
struct amdgpu_encoder_atom_dig *dig;
|
||||
struct amdgpu_connector *amdgpu_connector;
|
||||
struct amdgpu_connector_atom_dig *dig_connector;
|
||||
struct amdgpu_atombios_dp_link_train_info dp_info;
|
||||
@ -721,7 +717,6 @@ void amdgpu_atombios_dp_link_train(struct drm_encoder *encoder,
|
||||
|
||||
if (!amdgpu_encoder->enc_priv)
|
||||
return;
|
||||
dig = amdgpu_encoder->enc_priv;
|
||||
|
||||
amdgpu_connector = to_amdgpu_connector(connector);
|
||||
if (!amdgpu_connector->con_priv)
|
||||
|
@ -76,11 +76,6 @@ static int amdgpu_atombios_i2c_process_i2c_ch(struct amdgpu_i2c_chan *chan,
|
||||
}
|
||||
args.lpI2CDataOut = cpu_to_le16(out);
|
||||
} else {
|
||||
if (num > ATOM_MAX_HW_I2C_READ) {
|
||||
DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num);
|
||||
r = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
args.ucRegIndex = 0;
|
||||
args.lpI2CDataOut = 0;
|
||||
}
|
||||
|
@ -1310,6 +1310,23 @@ static int cik_asic_pci_config_reset(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool cik_asic_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
bool baco_support;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_HAWAII:
|
||||
smu7_asic_get_baco_capability(adev, &baco_support);
|
||||
break;
|
||||
default:
|
||||
baco_support = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return baco_support;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
cik_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -1927,6 +1944,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
|
||||
.get_pcie_usage = &cik_get_pcie_usage,
|
||||
.need_reset_on_init = &cik_need_reset_on_init,
|
||||
.get_pcie_replay_count = &cik_get_pcie_replay_count,
|
||||
.supports_baco = &cik_asic_supports_baco,
|
||||
};
|
||||
|
||||
static int cik_common_early_init(void *handle)
|
||||
|
@ -50,9 +50,6 @@
|
||||
* Navi10 has two graphic rings to share each graphic pipe.
|
||||
* 1. Primary ring
|
||||
* 2. Async ring
|
||||
*
|
||||
* In bring-up phase, it just used primary ring so set gfx ring number as 1 at
|
||||
* first.
|
||||
*/
|
||||
#define GFX10_NUM_GFX_RINGS 2
|
||||
#define GFX10_MEC_HPD_SIZE 2048
|
||||
@ -617,11 +614,29 @@ static void gfx_v10_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
|
||||
le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
|
||||
}
|
||||
|
||||
static bool gfx_v10_0_navi10_gfxoff_should_enable(struct amdgpu_device *adev)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
switch (adev->pdev->revision) {
|
||||
case 0xc2:
|
||||
case 0xc3:
|
||||
ret = true;
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret ;
|
||||
}
|
||||
|
||||
static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_NAVI10:
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
if (!gfx_v10_0_navi10_gfxoff_should_enable(adev))
|
||||
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1576,7 +1576,7 @@ static void gfx_v6_0_config_init(struct amdgpu_device *adev)
|
||||
static void gfx_v6_0_constants_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 gb_addr_config = 0;
|
||||
u32 mc_shared_chmap, mc_arb_ramcfg;
|
||||
u32 mc_arb_ramcfg;
|
||||
u32 sx_debug_1;
|
||||
u32 hdp_host_path_cntl;
|
||||
u32 tmp;
|
||||
@ -1678,7 +1678,6 @@ static void gfx_v6_0_constants_init(struct amdgpu_device *adev)
|
||||
|
||||
WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
|
||||
|
||||
mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
|
||||
adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
|
||||
mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
|
||||
|
||||
|
@ -4258,7 +4258,7 @@ static int gfx_v7_0_late_init(void *handle)
|
||||
static void gfx_v7_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 gb_addr_config;
|
||||
u32 mc_shared_chmap, mc_arb_ramcfg;
|
||||
u32 mc_arb_ramcfg;
|
||||
u32 dimm00_addr_map, dimm01_addr_map, dimm10_addr_map, dimm11_addr_map;
|
||||
u32 tmp;
|
||||
|
||||
@ -4335,7 +4335,6 @@ static void gfx_v7_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
|
||||
adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
|
||||
mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
|
||||
|
||||
|
@ -1677,7 +1677,7 @@ fail:
|
||||
static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 gb_addr_config;
|
||||
u32 mc_shared_chmap, mc_arb_ramcfg;
|
||||
u32 mc_arb_ramcfg;
|
||||
u32 dimm00_addr_map, dimm01_addr_map, dimm10_addr_map, dimm11_addr_map;
|
||||
u32 tmp;
|
||||
int ret;
|
||||
@ -1817,7 +1817,6 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
|
||||
adev->gfx.config.mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
|
||||
mc_arb_ramcfg = adev->gfx.config.mc_arb_ramcfg;
|
||||
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
#include "amdgpu_ras.h"
|
||||
|
||||
#include "sdma0/sdma0_4_0_offset.h"
|
||||
#include "sdma1/sdma1_4_0_offset.h"
|
||||
#define GFX9_NUM_GFX_RINGS 1
|
||||
#define GFX9_MEC_HPD_SIZE 4096
|
||||
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
|
||||
@ -131,18 +133,6 @@ MODULE_FIRMWARE("amdgpu/renoir_rlc.bin");
|
||||
#define mmTCP_CHAN_STEER_5_ARCT 0x0b0c
|
||||
#define mmTCP_CHAN_STEER_5_ARCT_BASE_IDX 0
|
||||
|
||||
struct ras_gfx_subblock_reg {
|
||||
const char *name;
|
||||
uint32_t hwip;
|
||||
uint32_t inst;
|
||||
uint32_t seg;
|
||||
uint32_t reg_offset;
|
||||
uint32_t sec_count_mask;
|
||||
uint32_t sec_count_shift;
|
||||
uint32_t ded_count_mask;
|
||||
uint32_t ded_count_shift;
|
||||
};
|
||||
|
||||
enum ta_ras_gfx_subblock {
|
||||
/*CPC*/
|
||||
TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0,
|
||||
@ -3948,24 +3938,37 @@ static const struct soc15_reg_entry vgpr_init_regs[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE1), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE2), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE3), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_RESOURCE_LIMITS), 0x1000000 }, /* CU_GROUP_COUNT=1 */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_X), 256*2 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Y), 1 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_RESOURCE_LIMITS), 0x0000000 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_X), 0x40 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Y), 4 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Z), 1 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC1), 0x100007f }, /* VGPRS=15 (256 logical VGPRs, SGPRS=1 (16 SGPRs, BULKY=1 */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC1), 0x3f },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC2), 0x400000 }, /* 64KB LDS */
|
||||
};
|
||||
|
||||
static const struct soc15_reg_entry sgpr_init_regs[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE0), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE1), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE2), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE3), 0xffffffff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_RESOURCE_LIMITS), 0x1000000 }, /* CU_GROUP_COUNT=1 */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_X), 256*2 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Y), 1 },
|
||||
static const struct soc15_reg_entry sgpr1_init_regs[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE0), 0x000000ff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE1), 0x000000ff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE2), 0x000000ff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE3), 0x000000ff },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_RESOURCE_LIMITS), 0x0000000 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_X), 0x40 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Y), 8 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Z), 1 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC1), 0x340 }, /* SGPRS=13 (112 GPRS) */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC1), 0x240 }, /* (80 GPRS) */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC2), 0x0 },
|
||||
};
|
||||
|
||||
static const struct soc15_reg_entry sgpr2_init_regs[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE0), 0x0000ff00 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE1), 0x0000ff00 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE2), 0x0000ff00 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_STATIC_THREAD_MGMT_SE3), 0x0000ff00 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_RESOURCE_LIMITS), 0x0000000 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_X), 0x40 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Y), 8 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_NUM_THREAD_Z), 1 },
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC1), 0x240 }, /* (80 GPRS) */
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmCOMPUTE_PGM_RSRC2), 0x0 },
|
||||
};
|
||||
|
||||
@ -4003,6 +4006,9 @@ static const struct soc15_reg_entry sec_ded_counter_registers[] = {
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCC_EDC_CNT2), 0, 1, 16},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmTCA_EDC_CNT), 0, 1, 2},
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT3), 0, 4, 6},
|
||||
{ SOC15_REG_ENTRY(SDMA0, 0, mmSDMA0_EDC_COUNTER), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(SDMA1, 0, mmSDMA1_EDC_COUNTER), 0, 1, 1},
|
||||
{ SOC15_REG_ENTRY(HDP, 0, mmHDP_EDC_CNT), 0, 1, 1},
|
||||
};
|
||||
|
||||
static int gfx_v9_0_do_edc_gds_workarounds(struct amdgpu_device *adev)
|
||||
@ -4072,7 +4078,9 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
total_size =
|
||||
((ARRAY_SIZE(vgpr_init_regs) * 3) + 4 + 5 + 2) * 4;
|
||||
total_size +=
|
||||
((ARRAY_SIZE(sgpr_init_regs) * 3) + 4 + 5 + 2) * 4;
|
||||
((ARRAY_SIZE(sgpr1_init_regs) * 3) + 4 + 5 + 2) * 4;
|
||||
total_size +=
|
||||
((ARRAY_SIZE(sgpr2_init_regs) * 3) + 4 + 5 + 2) * 4;
|
||||
total_size = ALIGN(total_size, 256);
|
||||
vgpr_offset = total_size;
|
||||
total_size += ALIGN(sizeof(vgpr_init_compute_shader), 256);
|
||||
@ -4115,7 +4123,7 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
|
||||
/* write dispatch packet */
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
|
||||
ib.ptr[ib.length_dw++] = 128; /* x */
|
||||
ib.ptr[ib.length_dw++] = 0x40*2; /* x */
|
||||
ib.ptr[ib.length_dw++] = 1; /* y */
|
||||
ib.ptr[ib.length_dw++] = 1; /* z */
|
||||
ib.ptr[ib.length_dw++] =
|
||||
@ -4125,13 +4133,13 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0);
|
||||
ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
|
||||
|
||||
/* SGPR */
|
||||
/* SGPR1 */
|
||||
/* write the register state for the compute dispatch */
|
||||
for (i = 0; i < ARRAY_SIZE(sgpr_init_regs); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(sgpr1_init_regs); i++) {
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1);
|
||||
ib.ptr[ib.length_dw++] = SOC15_REG_ENTRY_OFFSET(sgpr_init_regs[i])
|
||||
ib.ptr[ib.length_dw++] = SOC15_REG_ENTRY_OFFSET(sgpr1_init_regs[i])
|
||||
- PACKET3_SET_SH_REG_START;
|
||||
ib.ptr[ib.length_dw++] = sgpr_init_regs[i].reg_value;
|
||||
ib.ptr[ib.length_dw++] = sgpr1_init_regs[i].reg_value;
|
||||
}
|
||||
/* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */
|
||||
gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8;
|
||||
@ -4143,7 +4151,35 @@ static int gfx_v9_0_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
|
||||
/* write dispatch packet */
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
|
||||
ib.ptr[ib.length_dw++] = 128; /* x */
|
||||
ib.ptr[ib.length_dw++] = 0xA0*2; /* x */
|
||||
ib.ptr[ib.length_dw++] = 1; /* y */
|
||||
ib.ptr[ib.length_dw++] = 1; /* z */
|
||||
ib.ptr[ib.length_dw++] =
|
||||
REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1);
|
||||
|
||||
/* write CS partial flush packet */
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0);
|
||||
ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
|
||||
|
||||
/* SGPR2 */
|
||||
/* write the register state for the compute dispatch */
|
||||
for (i = 0; i < ARRAY_SIZE(sgpr2_init_regs); i++) {
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1);
|
||||
ib.ptr[ib.length_dw++] = SOC15_REG_ENTRY_OFFSET(sgpr2_init_regs[i])
|
||||
- PACKET3_SET_SH_REG_START;
|
||||
ib.ptr[ib.length_dw++] = sgpr2_init_regs[i].reg_value;
|
||||
}
|
||||
/* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */
|
||||
gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8;
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2);
|
||||
ib.ptr[ib.length_dw++] = SOC15_REG_OFFSET(GC, 0, mmCOMPUTE_PGM_LO)
|
||||
- PACKET3_SET_SH_REG_START;
|
||||
ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr);
|
||||
ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr);
|
||||
|
||||
/* write dispatch packet */
|
||||
ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3);
|
||||
ib.ptr[ib.length_dw++] = 0xA0*2; /* x */
|
||||
ib.ptr[ib.length_dw++] = 1; /* y */
|
||||
ib.ptr[ib.length_dw++] = 1; /* z */
|
||||
ib.ptr[ib.length_dw++] =
|
||||
@ -4209,10 +4245,6 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_gfx_ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfx_v9_0_do_edc_gds_workarounds(adev);
|
||||
if (r)
|
||||
return r;
|
||||
@ -4222,6 +4254,10 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_gfx_ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5447,7 +5483,7 @@ static int gfx_v9_0_priv_inst_irq(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
|
||||
static const struct ras_gfx_subblock_reg ras_subblock_regs[] = {
|
||||
static const struct soc15_ras_field_entry gc_ras_fields_vg20[] = {
|
||||
{ "CPC_SCRATCH", SOC15_REG_ENTRY(GC, 0, mmCPC_EDC_SCRATCH_CNT),
|
||||
SOC15_REG_FIELD(CPC_EDC_SCRATCH_CNT, SEC_COUNT),
|
||||
SOC15_REG_FIELD(CPC_EDC_SCRATCH_CNT, DED_COUNT)
|
||||
@ -6106,29 +6142,29 @@ static int __get_ras_error_count(const struct soc15_reg_entry *reg,
|
||||
uint32_t i;
|
||||
uint32_t sec_cnt, ded_cnt;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ras_subblock_regs); i++) {
|
||||
if(ras_subblock_regs[i].reg_offset != reg->reg_offset ||
|
||||
ras_subblock_regs[i].seg != reg->seg ||
|
||||
ras_subblock_regs[i].inst != reg->inst)
|
||||
for (i = 0; i < ARRAY_SIZE(gc_ras_fields_vg20); i++) {
|
||||
if(gc_ras_fields_vg20[i].reg_offset != reg->reg_offset ||
|
||||
gc_ras_fields_vg20[i].seg != reg->seg ||
|
||||
gc_ras_fields_vg20[i].inst != reg->inst)
|
||||
continue;
|
||||
|
||||
sec_cnt = (value &
|
||||
ras_subblock_regs[i].sec_count_mask) >>
|
||||
ras_subblock_regs[i].sec_count_shift;
|
||||
gc_ras_fields_vg20[i].sec_count_mask) >>
|
||||
gc_ras_fields_vg20[i].sec_count_shift;
|
||||
if (sec_cnt) {
|
||||
DRM_INFO("GFX SubBlock %s, Instance[%d][%d], SEC %d\n",
|
||||
ras_subblock_regs[i].name,
|
||||
gc_ras_fields_vg20[i].name,
|
||||
se_id, inst_id,
|
||||
sec_cnt);
|
||||
*sec_count += sec_cnt;
|
||||
}
|
||||
|
||||
ded_cnt = (value &
|
||||
ras_subblock_regs[i].ded_count_mask) >>
|
||||
ras_subblock_regs[i].ded_count_shift;
|
||||
gc_ras_fields_vg20[i].ded_count_mask) >>
|
||||
gc_ras_fields_vg20[i].ded_count_shift;
|
||||
if (ded_cnt) {
|
||||
DRM_INFO("GFX SubBlock %s, Instance[%d][%d], DED %d\n",
|
||||
ras_subblock_regs[i].name,
|
||||
gc_ras_fields_vg20[i].name,
|
||||
se_id, inst_id,
|
||||
ded_cnt);
|
||||
*ded_count += ded_cnt;
|
||||
|
@ -715,7 +715,15 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
|
||||
adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_VG20;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.funcs = &umc_v6_1_funcs;
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
|
||||
adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_ARCT;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.funcs = &umc_v6_1_funcs;
|
||||
break;
|
||||
@ -730,6 +738,9 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
||||
case CHIP_VEGA20:
|
||||
adev->mmhub.funcs = &mmhub_v1_0_funcs;
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
adev->mmhub.funcs = &mmhub_v9_4_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -825,6 +836,7 @@ static int gmc_v9_0_late_init(void *handle)
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
r = amdgpu_atomfirmware_mem_ecc_supported(adev);
|
||||
if (!r) {
|
||||
DRM_INFO("ECC is not present.\n");
|
||||
|
@ -36,12 +36,4 @@
|
||||
|
||||
extern const struct amd_ip_funcs gmc_v9_0_ip_funcs;
|
||||
extern const struct amdgpu_ip_block_version gmc_v9_0_ip_block;
|
||||
|
||||
/* amdgpu_amdkfd*.c */
|
||||
void gfxhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint64_t value);
|
||||
void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint64_t value);
|
||||
void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, int hubid,
|
||||
uint32_t vmid, uint64_t value);
|
||||
#endif
|
||||
|
585
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
Normal file
585
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_jpeg.h"
|
||||
#include "soc15.h"
|
||||
#include "soc15d.h"
|
||||
|
||||
#include "vcn/vcn_1_0_offset.h"
|
||||
#include "vcn/vcn_1_0_sh_mask.h"
|
||||
|
||||
static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
|
||||
static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[(*ptr)++] = 0;
|
||||
ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0);
|
||||
} else {
|
||||
ring->ring[(*ptr)++] = reg_offset;
|
||||
ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0);
|
||||
}
|
||||
ring->ring[(*ptr)++] = val;
|
||||
}
|
||||
|
||||
static void jpeg_v1_0_decode_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
uint32_t reg, reg_offset, val, mask, i;
|
||||
|
||||
// 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW);
|
||||
reg_offset = (reg << 2);
|
||||
val = lower_32_bits(ring->gpu_addr);
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH);
|
||||
reg_offset = (reg << 2);
|
||||
val = upper_32_bits(ring->gpu_addr);
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 3rd to 5th: issue MEM_READ commands
|
||||
for (i = 0; i <= 2; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
// 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x13;
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 7th: program mmUVD_JRBC_RB_REF_DATA
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 8th: issue conditional register read mmUVD_JRBC_RB_CNTL
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
mask = 0x1;
|
||||
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = 0x01400200;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = val;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[ptr++] = 0;
|
||||
ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3);
|
||||
} else {
|
||||
ring->ring[ptr++] = reg_offset;
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3);
|
||||
}
|
||||
ring->ring[ptr++] = mask;
|
||||
|
||||
//9th to 21st: insert no-op
|
||||
for (i = 0; i <= 12; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
//22nd: reset mmUVD_JRBC_RB_RPTR
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_RPTR);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0;
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
//23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch
|
||||
reg = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x12;
|
||||
jpeg_v1_0_decode_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t jpeg_v1_0_decode_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t jpeg_v1_0_decode_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void jpeg_v1_0_decode_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_insert_start - insert a start command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a start command to the ring.
|
||||
*/
|
||||
static void jpeg_v1_0_decode_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_insert_end - insert a end command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a end command to the ring.
|
||||
*/
|
||||
static void jpeg_v1_0_decode_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_emit_fence - emit an fence & trap command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @fence: fence to emit
|
||||
*
|
||||
* Write a fence and a trap command to the ring.
|
||||
*/
|
||||
static void jpeg_v1_0_decode_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA0), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_DATA1), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x8);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_GPCOM_CMD), 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0xffffffff);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x3fbc);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x1);
|
||||
|
||||
/* emit trap */
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_decode_ring_emit_ib - execute indirect buffer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @ib: indirect buffer to execute
|
||||
*
|
||||
* Write ring commands to execute the indirect buffer.
|
||||
*/
|
||||
static void jpeg_v1_0_decode_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_IB_SIZE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, ib->length_dw);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_STATUS), 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
}
|
||||
|
||||
static void jpeg_v1_0_decode_ring_emit_reg_wait(struct amdgpu_ring *ring,
|
||||
uint32_t reg, uint32_t val,
|
||||
uint32_t mask)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, val);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE3));
|
||||
}
|
||||
amdgpu_ring_write(ring, mask);
|
||||
}
|
||||
|
||||
static void jpeg_v1_0_decode_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||
uint32_t data0, data1, mask;
|
||||
|
||||
pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
|
||||
|
||||
/* wait for register write */
|
||||
data0 = hub->ctx0_ptb_addr_lo32 + vmid * 2;
|
||||
data1 = lower_32_bits(pd_addr);
|
||||
mask = 0xffffffff;
|
||||
jpeg_v1_0_decode_ring_emit_reg_wait(ring, data0, data1, mask);
|
||||
}
|
||||
|
||||
static void jpeg_v1_0_decode_ring_emit_wreg(struct amdgpu_ring *ring,
|
||||
uint32_t reg, uint32_t val)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
}
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
static void jpeg_v1_0_decode_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
WARN_ON(ring->wptr % 2 || count % 2);
|
||||
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int jpeg_v1_0_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v1_0_process_interrupt(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_DEBUG("IH: JPEG decode TRAP\n");
|
||||
|
||||
switch (entry->src_id) {
|
||||
case 126:
|
||||
amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_early_init - set function pointers
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Set ring and irq function pointers
|
||||
*/
|
||||
int jpeg_v1_0_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
adev->jpeg.num_jpeg_inst = 1;
|
||||
|
||||
jpeg_v1_0_set_dec_ring_funcs(adev);
|
||||
jpeg_v1_0_set_irq_funcs(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_sw_init - sw init for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
int jpeg_v1_0_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring;
|
||||
int r;
|
||||
|
||||
/* JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 126, &adev->jpeg.inst->irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ring = &adev->jpeg.inst->ring_dec;
|
||||
sprintf(ring->name, "jpeg_dec");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->jpeg.internal.jpeg_pitch = adev->jpeg.inst->external.jpeg_pitch =
|
||||
SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_sw_fini - sw fini for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* JPEG free up sw allocation
|
||||
*/
|
||||
void jpeg_v1_0_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_ring_fini(&adev->jpeg.inst[0].ring_dec);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v1_0_start - start JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup and start the JPEG block
|
||||
*/
|
||||
void jpeg_v1_0_start(struct amdgpu_device *adev, int mode)
|
||||
{
|
||||
struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
|
||||
|
||||
if (mode == 0) {
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
|
||||
UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
|
||||
}
|
||||
|
||||
/* initialize wptr */
|
||||
ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
|
||||
|
||||
/* copy patch commands to the jpeg ring */
|
||||
jpeg_v1_0_decode_ring_set_patch_ring(ring,
|
||||
(ring->wptr + ring->max_dw * amdgpu_sched_hw_submission));
|
||||
}
|
||||
|
||||
static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.nop = PACKET0(0x81ff, 0),
|
||||
.support_64bit_ptrs = false,
|
||||
.no_user_fence = true,
|
||||
.vmhub = AMDGPU_MMHUB_0,
|
||||
.extra_dw = 64,
|
||||
.get_rptr = jpeg_v1_0_decode_ring_get_rptr,
|
||||
.get_wptr = jpeg_v1_0_decode_ring_get_wptr,
|
||||
.set_wptr = jpeg_v1_0_decode_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
6 + 6 + /* hdp invalidate / flush */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* jpeg_v1_0_decode_ring_emit_vm_flush */
|
||||
26 + 26 + /* jpeg_v1_0_decode_ring_emit_fence x2 vm fence */
|
||||
6,
|
||||
.emit_ib_size = 22, /* jpeg_v1_0_decode_ring_emit_ib */
|
||||
.emit_ib = jpeg_v1_0_decode_ring_emit_ib,
|
||||
.emit_fence = jpeg_v1_0_decode_ring_emit_fence,
|
||||
.emit_vm_flush = jpeg_v1_0_decode_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_jpeg_dec_ring_test_ring,
|
||||
.test_ib = amdgpu_jpeg_dec_ring_test_ib,
|
||||
.insert_nop = jpeg_v1_0_decode_ring_nop,
|
||||
.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,
|
||||
.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,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec.funcs = &jpeg_v1_0_decode_ring_vm_funcs;
|
||||
DRM_INFO("JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v1_0_irq_funcs = {
|
||||
.set = jpeg_v1_0_set_interrupt_state,
|
||||
.process = jpeg_v1_0_process_interrupt,
|
||||
};
|
||||
|
||||
static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs;
|
||||
}
|
32
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.h
Normal file
32
drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __JPEG_V1_0_H__
|
||||
#define __JPEG_V1_0_H__
|
||||
|
||||
int jpeg_v1_0_early_init(void *handle);
|
||||
int jpeg_v1_0_sw_init(void *handle);
|
||||
void jpeg_v1_0_sw_fini(void *handle);
|
||||
void jpeg_v1_0_start(struct amdgpu_device *adev, int mode);
|
||||
|
||||
#endif /*__JPEG_V1_0_H__*/
|
827
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
Normal file
827
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
Normal file
@ -0,0 +1,827 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_jpeg.h"
|
||||
#include "amdgpu_pm.h"
|
||||
#include "soc15.h"
|
||||
#include "soc15d.h"
|
||||
|
||||
#include "vcn/vcn_2_0_0_offset.h"
|
||||
#include "vcn/vcn_2_0_0_sh_mask.h"
|
||||
#include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
|
||||
|
||||
#define mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET 0x1bfff
|
||||
#define mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET 0x4029
|
||||
#define mmUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET 0x402a
|
||||
#define mmUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET 0x402b
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40ea
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40eb
|
||||
#define mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET 0x40cf
|
||||
#define mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET 0x40d1
|
||||
#define mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40e8
|
||||
#define mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40e9
|
||||
#define mmUVD_JRBC_IB_SIZE_INTERNAL_OFFSET 0x4082
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40ec
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40ed
|
||||
#define mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET 0x4085
|
||||
#define mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET 0x4084
|
||||
#define mmUVD_JRBC_STATUS_INTERNAL_OFFSET 0x4089
|
||||
#define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
|
||||
|
||||
#define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000
|
||||
|
||||
static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void jpeg_v2_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static int jpeg_v2_0_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state);
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_early_init - set function pointers
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Set ring and irq function pointers
|
||||
*/
|
||||
static int jpeg_v2_0_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
adev->jpeg.num_jpeg_inst = 1;
|
||||
|
||||
jpeg_v2_0_set_dec_ring_funcs(adev);
|
||||
jpeg_v2_0_set_irq_funcs(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_sw_init - sw init for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Load firmware and sw initialization
|
||||
*/
|
||||
static int jpeg_v2_0_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring;
|
||||
int r;
|
||||
|
||||
/* JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
|
||||
VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst->irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_sw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ring = &adev->jpeg.inst->ring_dec;
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
|
||||
sprintf(ring->name, "jpeg_dec");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
|
||||
adev->jpeg.inst->external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_PITCH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_sw_fini - sw fini for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* JPEG suspend and free up sw allocation
|
||||
*/
|
||||
static int jpeg_v2_0_sw_fini(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = amdgpu_jpeg_suspend(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_sw_fini(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_hw_init - start and test JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int jpeg_v2_0_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
|
||||
int r;
|
||||
|
||||
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
|
||||
(adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (!r)
|
||||
DRM_INFO("JPEG decode initialized successfully.\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_hw_fini - stop the hardware block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Stop the JPEG block, mark ring as not ready any more
|
||||
*/
|
||||
static int jpeg_v2_0_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
|
||||
|
||||
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
||||
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
|
||||
jpeg_v2_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
||||
|
||||
ring->sched.ready = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_suspend - suspend JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* HW fini and suspend JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = jpeg_v2_0_hw_fini(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_suspend(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_resume - resume JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Resume firmware and hw init JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_resume(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = amdgpu_jpeg_resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = jpeg_v2_0_hw_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_disable_power_gating(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t data;
|
||||
int r = 0;
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
|
||||
data = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
|
||||
WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data);
|
||||
|
||||
SOC15_WAIT_ON_RREG(JPEG, 0,
|
||||
mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON,
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK, r);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu: JPEG disable power gating failed\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Removing the anti hang mechanism to indicate the UVDJ tile is ON */
|
||||
data = RREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS)) & ~0x1;
|
||||
WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_enable_power_gating(struct amdgpu_device* adev)
|
||||
{
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_JPEG) {
|
||||
uint32_t data;
|
||||
int r = 0;
|
||||
|
||||
data = RREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS));
|
||||
data &= ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK;
|
||||
data |= 0x1; //UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_TILES_OFF;
|
||||
WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JPEG_POWER_STATUS), data);
|
||||
|
||||
data = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
|
||||
WREG32(SOC15_REG_OFFSET(JPEG, 0, mmUVD_PGFSM_CONFIG), data);
|
||||
|
||||
SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_PGFSM_STATUS,
|
||||
(2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT),
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK, r);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu: JPEG enable power gating failed\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jpeg_v2_0_disable_clock_gating(struct amdgpu_device* adev)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL);
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
|
||||
data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
else
|
||||
data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
|
||||
data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data);
|
||||
|
||||
data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE);
|
||||
data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
| JPEG_CGC_GATE__JMCIF_MASK
|
||||
| JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data);
|
||||
}
|
||||
|
||||
static void jpeg_v2_0_enable_clock_gating(struct amdgpu_device* adev)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL);
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
|
||||
data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
else
|
||||
data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
|
||||
data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(JPEG, 0, mmJPEG_CGC_CTRL, data);
|
||||
|
||||
data = RREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE);
|
||||
data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
|JPEG_CGC_GATE__JMCIF_MASK
|
||||
|JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(JPEG, 0, mmJPEG_CGC_GATE, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_start - start JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup and start the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring = &adev->jpeg.inst->ring_dec;
|
||||
int r;
|
||||
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_jpeg(adev, true);
|
||||
|
||||
/* disable power gating */
|
||||
r = jpeg_v2_0_disable_power_gating(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* JPEG disable CGC */
|
||||
jpeg_v2_0_disable_clock_gating(adev);
|
||||
|
||||
WREG32_SOC15(JPEG, 0, mmJPEG_DEC_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmJPEG_SYS_INT_EN),
|
||||
JPEG_SYS_INT_EN__DJRBC_MASK,
|
||||
~JPEG_SYS_INT_EN__DJRBC_MASK);
|
||||
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_stop - stop JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* stop the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, 0, mmUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable JPEG CGC */
|
||||
jpeg_v2_0_enable_clock_gating(adev);
|
||||
|
||||
/* enable power gating */
|
||||
r = jpeg_v2_0_enable_power_gating(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_jpeg(adev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t jpeg_v2_0_dec_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t jpeg_v2_0_dec_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell)
|
||||
return adev->wb.wb[ring->wptr_offs];
|
||||
else
|
||||
return RREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void jpeg_v2_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell) {
|
||||
adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
|
||||
WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
|
||||
} else {
|
||||
WREG32_SOC15(JPEG, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_insert_start - insert a start command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a start command to the ring.
|
||||
*/
|
||||
void jpeg_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_insert_end - insert a end command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a end command to the ring.
|
||||
*/
|
||||
void jpeg_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_emit_fence - emit an fence & trap command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @fence: fence to emit
|
||||
*
|
||||
* Write a fence and a trap command to the ring.
|
||||
*/
|
||||
void jpeg_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags)
|
||||
{
|
||||
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x8);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
|
||||
0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x3fbc);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x1);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_dec_ring_emit_ib - execute indirect buffer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @ib: indirect buffer to execute
|
||||
*
|
||||
* Write ring commands to execute the indirect buffer.
|
||||
*/
|
||||
void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_IB_SIZE_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, ib->length_dw);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_STATUS_INTERNAL_OFFSET,
|
||||
0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
}
|
||||
|
||||
void jpeg_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask)
|
||||
{
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, val);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE3));
|
||||
}
|
||||
amdgpu_ring_write(ring, mask);
|
||||
}
|
||||
|
||||
void jpeg_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||
uint32_t data0, data1, mask;
|
||||
|
||||
pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
|
||||
|
||||
/* wait for register write */
|
||||
data0 = hub->ctx0_ptb_addr_lo32 + vmid * 2;
|
||||
data1 = lower_32_bits(pd_addr);
|
||||
mask = 0xffffffff;
|
||||
jpeg_v2_0_dec_ring_emit_reg_wait(ring, data0, data1, mask);
|
||||
}
|
||||
|
||||
void jpeg_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
|
||||
{
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
}
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
WARN_ON(ring->wptr % 2 || count % 2);
|
||||
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v2_0_is_idle(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
return ((RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS) &
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK);
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_wait_for_idle(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int ret = 0;
|
||||
|
||||
SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
|
||||
|
||||
if (enable) {
|
||||
if (jpeg_v2_0_is_idle(handle))
|
||||
return -EBUSY;
|
||||
jpeg_v2_0_enable_clock_gating(adev);
|
||||
} else {
|
||||
jpeg_v2_0_disable_clock_gating(adev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int ret;
|
||||
|
||||
if (state == adev->jpeg.cur_state)
|
||||
return 0;
|
||||
|
||||
if (state == AMD_PG_STATE_GATE)
|
||||
ret = jpeg_v2_0_stop(adev);
|
||||
else
|
||||
ret = jpeg_v2_0_start(adev);
|
||||
|
||||
if (!ret)
|
||||
adev->jpeg.cur_state = state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
DRM_DEBUG("IH: JPEG TRAP\n");
|
||||
|
||||
switch (entry->src_id) {
|
||||
case VCN_2_0__SRCID__JPEG_DECODE:
|
||||
amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
|
||||
.name = "jpeg_v2_0",
|
||||
.early_init = jpeg_v2_0_early_init,
|
||||
.late_init = NULL,
|
||||
.sw_init = jpeg_v2_0_sw_init,
|
||||
.sw_fini = jpeg_v2_0_sw_fini,
|
||||
.hw_init = jpeg_v2_0_hw_init,
|
||||
.hw_fini = jpeg_v2_0_hw_fini,
|
||||
.suspend = jpeg_v2_0_suspend,
|
||||
.resume = jpeg_v2_0_resume,
|
||||
.is_idle = jpeg_v2_0_is_idle,
|
||||
.wait_for_idle = jpeg_v2_0_wait_for_idle,
|
||||
.check_soft_reset = NULL,
|
||||
.pre_soft_reset = NULL,
|
||||
.soft_reset = NULL,
|
||||
.post_soft_reset = NULL,
|
||||
.set_clockgating_state = jpeg_v2_0_set_clockgating_state,
|
||||
.set_powergating_state = jpeg_v2_0_set_powergating_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.vmhub = AMDGPU_MMHUB_0,
|
||||
.get_rptr = jpeg_v2_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_0_dec_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* jpeg_v2_0_dec_ring_emit_vm_flush */
|
||||
18 + 18 + /* jpeg_v2_0_dec_ring_emit_fence x2 vm fence */
|
||||
8 + 16,
|
||||
.emit_ib_size = 22, /* jpeg_v2_0_dec_ring_emit_ib */
|
||||
.emit_ib = jpeg_v2_0_dec_ring_emit_ib,
|
||||
.emit_fence = jpeg_v2_0_dec_ring_emit_fence,
|
||||
.emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_jpeg_dec_ring_test_ring,
|
||||
.test_ib = amdgpu_jpeg_dec_ring_test_ib,
|
||||
.insert_nop = jpeg_v2_0_dec_ring_nop,
|
||||
.insert_start = jpeg_v2_0_dec_ring_insert_start,
|
||||
.insert_end = jpeg_v2_0_dec_ring_insert_end,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.begin_use = amdgpu_jpeg_ring_begin_use,
|
||||
.end_use = amdgpu_jpeg_ring_end_use,
|
||||
.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
|
||||
.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void jpeg_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->ring_dec.funcs = &jpeg_v2_0_dec_ring_vm_funcs;
|
||||
DRM_INFO("JPEG decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v2_0_irq_funcs = {
|
||||
.set = jpeg_v2_0_set_interrupt_state,
|
||||
.process = jpeg_v2_0_process_interrupt,
|
||||
};
|
||||
|
||||
static void jpeg_v2_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->jpeg.inst->irq.num_types = 1;
|
||||
adev->jpeg.inst->irq.funcs = &jpeg_v2_0_irq_funcs;
|
||||
}
|
||||
|
||||
const struct amdgpu_ip_block_version jpeg_v2_0_ip_block =
|
||||
{
|
||||
.type = AMD_IP_BLOCK_TYPE_JPEG,
|
||||
.major = 2,
|
||||
.minor = 0,
|
||||
.rev = 0,
|
||||
.funcs = &jpeg_v2_0_ip_funcs,
|
||||
};
|
42
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h
Normal file
42
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __JPEG_V2_0_H__
|
||||
#define __JPEG_V2_0_H__
|
||||
|
||||
void jpeg_v2_0_dec_ring_insert_start(struct amdgpu_ring *ring);
|
||||
void jpeg_v2_0_dec_ring_insert_end(struct amdgpu_ring *ring);
|
||||
void jpeg_v2_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags);
|
||||
void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib, uint32_t flags);
|
||||
void jpeg_v2_0_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask);
|
||||
void jpeg_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr);
|
||||
void jpeg_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
|
||||
void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count);
|
||||
|
||||
extern const struct amdgpu_ip_block_version jpeg_v2_0_ip_block;
|
||||
|
||||
#endif /* __JPEG_V2_0_H__ */
|
641
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
Normal file
641
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
Normal file
@ -0,0 +1,641 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_jpeg.h"
|
||||
#include "soc15.h"
|
||||
#include "soc15d.h"
|
||||
#include "jpeg_v2_0.h"
|
||||
|
||||
#include "vcn/vcn_2_5_offset.h"
|
||||
#include "vcn/vcn_2_5_sh_mask.h"
|
||||
#include "ivsrcid/vcn/irqsrcs_vcn_2_0.h"
|
||||
|
||||
#define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
|
||||
|
||||
#define JPEG25_MAX_HW_INSTANCES_ARCTURUS 2
|
||||
|
||||
static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static int jpeg_v2_5_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state);
|
||||
|
||||
static int amdgpu_ih_clientid_jpeg[] = {
|
||||
SOC15_IH_CLIENTID_VCN,
|
||||
SOC15_IH_CLIENTID_VCN1
|
||||
};
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_early_init - set function pointers
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Set ring and irq function pointers
|
||||
*/
|
||||
static int jpeg_v2_5_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
u32 harvest;
|
||||
int i;
|
||||
|
||||
adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS;
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) {
|
||||
harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING);
|
||||
if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK)
|
||||
adev->jpeg.harvest_config |= 1 << i;
|
||||
}
|
||||
|
||||
if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 |
|
||||
AMDGPU_JPEG_HARVEST_JPEG1))
|
||||
return -ENOENT;
|
||||
} else
|
||||
adev->jpeg.num_jpeg_inst = 1;
|
||||
|
||||
jpeg_v2_5_set_dec_ring_funcs(adev);
|
||||
jpeg_v2_5_set_irq_funcs(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_sw_init - sw init for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Load firmware and sw initialization
|
||||
*/
|
||||
static int jpeg_v2_5_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i, r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
/* JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i],
|
||||
VCN_2_0__SRCID__JPEG_DECODE, &adev->jpeg.inst[i].irq);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_jpeg_sw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
ring = &adev->jpeg.inst[i].ring_dec;
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;
|
||||
sprintf(ring->name, "jpeg_dec_%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->jpeg.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
|
||||
adev->jpeg.inst[i].external.jpeg_pitch = SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_PITCH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_sw_fini - sw fini for JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* JPEG suspend and free up sw allocation
|
||||
*/
|
||||
static int jpeg_v2_5_sw_fini(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
r = amdgpu_jpeg_suspend(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_sw_fini(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_hw_init - start and test JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
*/
|
||||
static int jpeg_v2_5_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
ring = &adev->jpeg.inst[i].ring_dec;
|
||||
adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
|
||||
(adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i, i);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
DRM_INFO("JPEG decode initialized successfully.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_hw_fini - stop the hardware block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Stop the JPEG block, mark ring as not ready any more
|
||||
*/
|
||||
static int jpeg_v2_5_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct amdgpu_ring *ring;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
ring = &adev->jpeg.inst[i].ring_dec;
|
||||
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
|
||||
RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
|
||||
jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
|
||||
|
||||
ring->sched.ready = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_suspend - suspend JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* HW fini and suspend JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = jpeg_v2_5_hw_fini(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_jpeg_suspend(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_resume - resume JPEG block
|
||||
*
|
||||
* @handle: amdgpu_device pointer
|
||||
*
|
||||
* Resume firmware and hw init JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_resume(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_jpeg_resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = jpeg_v2_5_hw_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void jpeg_v2_5_disable_clock_gating(struct amdgpu_device* adev, int inst)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
|
||||
if (adev->cg_flags & AMD_CG_SUPPORT_JPEG_MGCG)
|
||||
data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
else
|
||||
data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
|
||||
data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
|
||||
|
||||
data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
|
||||
data &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
| JPEG_CGC_GATE__JMCIF_MASK
|
||||
| JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
|
||||
|
||||
data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL);
|
||||
data &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JMCIF_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JRBBM_MODE_MASK);
|
||||
WREG32_SOC15(JPEG, inst, mmJPEG_CGC_CTRL, data);
|
||||
}
|
||||
|
||||
static void jpeg_v2_5_enable_clock_gating(struct amdgpu_device* adev, int inst)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
data = RREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE);
|
||||
data |= (JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
|JPEG_CGC_GATE__JMCIF_MASK
|
||||
|JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(JPEG, inst, mmJPEG_CGC_GATE, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_start - start JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup and start the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
ring = &adev->jpeg.inst[i].ring_dec;
|
||||
/* disable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
|
||||
/* JPEG disable CGC */
|
||||
jpeg_v2_5_disable_clock_gating(adev, i);
|
||||
|
||||
/* MJPEG global tiling registers */
|
||||
WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX8_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
WREG32_SOC15(JPEG, i, mmJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmJPEG_SYS_INT_EN),
|
||||
JPEG_SYS_INT_EN__DJRBC_MASK,
|
||||
~JPEG_SYS_INT_EN__DJRBC_MASK);
|
||||
|
||||
WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_CNTL, 0x00000002L);
|
||||
WREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15(JPEG, i, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_stop - stop JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* stop the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
jpeg_v2_5_enable_clock_gating(adev, i);
|
||||
|
||||
/* enable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(JPEG, i, mmUVD_JPEG_POWER_STATUS),
|
||||
UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_dec_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t jpeg_v2_5_dec_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_dec_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t jpeg_v2_5_dec_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell)
|
||||
return adev->wb.wb[ring->wptr_offs];
|
||||
else
|
||||
return RREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_dec_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void jpeg_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell) {
|
||||
adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
|
||||
WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
|
||||
} else {
|
||||
WREG32_SOC15(JPEG, ring->me, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
}
|
||||
|
||||
static bool jpeg_v2_5_is_idle(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, ret = 1;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
ret &= (((RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS) &
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK) ==
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jpeg_v2_5_wait_for_idle(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
SOC15_WAIT_ON_RREG(JPEG, i, mmUVD_JRBC_STATUS,
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK,
|
||||
UVD_JRBC_STATUS__RB_JOB_DONE_MASK, ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jpeg_v2_5_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
if (enable) {
|
||||
if (jpeg_v2_5_is_idle(handle))
|
||||
return -EBUSY;
|
||||
jpeg_v2_5_enable_clock_gating(adev, i);
|
||||
} else {
|
||||
jpeg_v2_5_disable_clock_gating(adev, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v2_5_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int ret;
|
||||
|
||||
if(state == adev->jpeg.cur_state)
|
||||
return 0;
|
||||
|
||||
if (state == AMD_PG_STATE_GATE)
|
||||
ret = jpeg_v2_5_stop(adev);
|
||||
else
|
||||
ret = jpeg_v2_5_start(adev);
|
||||
|
||||
if(!ret)
|
||||
adev->jpeg.cur_state = state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
uint32_t ip_instance;
|
||||
|
||||
switch (entry->client_id) {
|
||||
case SOC15_IH_CLIENTID_VCN:
|
||||
ip_instance = 0;
|
||||
break;
|
||||
case SOC15_IH_CLIENTID_VCN1:
|
||||
ip_instance = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_DEBUG("IH: JPEG TRAP\n");
|
||||
|
||||
switch (entry->src_id) {
|
||||
case VCN_2_0__SRCID__JPEG_DECODE:
|
||||
amdgpu_fence_process(&adev->jpeg.inst[ip_instance].ring_dec);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
|
||||
.name = "jpeg_v2_5",
|
||||
.early_init = jpeg_v2_5_early_init,
|
||||
.late_init = NULL,
|
||||
.sw_init = jpeg_v2_5_sw_init,
|
||||
.sw_fini = jpeg_v2_5_sw_fini,
|
||||
.hw_init = jpeg_v2_5_hw_init,
|
||||
.hw_fini = jpeg_v2_5_hw_fini,
|
||||
.suspend = jpeg_v2_5_suspend,
|
||||
.resume = jpeg_v2_5_resume,
|
||||
.is_idle = jpeg_v2_5_is_idle,
|
||||
.wait_for_idle = jpeg_v2_5_wait_for_idle,
|
||||
.check_soft_reset = NULL,
|
||||
.pre_soft_reset = NULL,
|
||||
.soft_reset = NULL,
|
||||
.post_soft_reset = NULL,
|
||||
.set_clockgating_state = jpeg_v2_5_set_clockgating_state,
|
||||
.set_powergating_state = jpeg_v2_5_set_powergating_state,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.vmhub = AMDGPU_MMHUB_1,
|
||||
.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* jpeg_v2_5_dec_ring_emit_vm_flush */
|
||||
18 + 18 + /* jpeg_v2_5_dec_ring_emit_fence x2 vm fence */
|
||||
8 + 16,
|
||||
.emit_ib_size = 22, /* jpeg_v2_5_dec_ring_emit_ib */
|
||||
.emit_ib = jpeg_v2_0_dec_ring_emit_ib,
|
||||
.emit_fence = jpeg_v2_0_dec_ring_emit_fence,
|
||||
.emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_jpeg_dec_ring_test_ring,
|
||||
.test_ib = amdgpu_jpeg_dec_ring_test_ib,
|
||||
.insert_nop = jpeg_v2_0_dec_ring_nop,
|
||||
.insert_start = jpeg_v2_0_dec_ring_insert_start,
|
||||
.insert_end = jpeg_v2_0_dec_ring_insert_end,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.begin_use = amdgpu_jpeg_ring_begin_use,
|
||||
.end_use = amdgpu_jpeg_ring_end_use,
|
||||
.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
|
||||
.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
adev->jpeg.inst[i].ring_dec.funcs = &jpeg_v2_5_dec_ring_vm_funcs;
|
||||
adev->jpeg.inst[i].ring_dec.me = i;
|
||||
DRM_INFO("JPEG(%d) JPEG decode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = {
|
||||
.set = jpeg_v2_5_set_interrupt_state,
|
||||
.process = jpeg_v2_5_process_interrupt,
|
||||
};
|
||||
|
||||
static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
|
||||
if (adev->jpeg.harvest_config & (1 << i))
|
||||
continue;
|
||||
|
||||
adev->jpeg.inst[i].irq.num_types = 1;
|
||||
adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs;
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_ip_block_version jpeg_v2_5_ip_block =
|
||||
{
|
||||
.type = AMD_IP_BLOCK_TYPE_JPEG,
|
||||
.major = 2,
|
||||
.minor = 5,
|
||||
.rev = 0,
|
||||
.funcs = &jpeg_v2_5_ip_funcs,
|
||||
};
|
29
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h
Normal file
29
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2019 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __JPEG_V2_5_H__
|
||||
#define __JPEG_V2_5_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version jpeg_v2_5_ip_block;
|
||||
|
||||
#endif /* __JPEG_V2_5_H__ */
|
@ -27,17 +27,13 @@
|
||||
#include "mmhub/mmhub_1_0_offset.h"
|
||||
#include "mmhub/mmhub_1_0_sh_mask.h"
|
||||
#include "mmhub/mmhub_1_0_default.h"
|
||||
#include "mmhub/mmhub_9_4_0_offset.h"
|
||||
#include "vega10_enum.h"
|
||||
|
||||
#include "soc15.h"
|
||||
#include "soc15_common.h"
|
||||
|
||||
#define mmDAGB0_CNTL_MISC2_RV 0x008f
|
||||
#define mmDAGB0_CNTL_MISC2_RV_BASE_IDX 0
|
||||
|
||||
#define EA_EDC_CNT_MASK 0x3
|
||||
#define EA_EDC_CNT_SHIFT 0x2
|
||||
|
||||
u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev)
|
||||
{
|
||||
u64 base = RREG32_SOC15(MMHUB, 0, mmMC_VM_FB_LOCATION_BASE);
|
||||
@ -564,59 +560,191 @@ void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
*flags |= AMD_CG_SUPPORT_MC_LS;
|
||||
}
|
||||
|
||||
static const struct soc15_ras_field_entry mmhub_v1_0_ras_fields[] = {
|
||||
{ "MMEA0_DRAMRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_RRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, RRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, RRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_WRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, WRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, WRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, DRAMWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, IORD_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, IOWR_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT_VG20, IOWR_DATAMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_GMIRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2_VG20, GMIWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_DRAMRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_RRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, RRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, RRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_WRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, WRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, WRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, DRAMWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, IORD_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, IOWR_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT_VG20, IOWR_DATAMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_GMIRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2_VG20, GMIWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct soc15_reg_entry mmhub_v1_0_edc_cnt_regs[] = {
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT_VG20), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT_VG20), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20), 0, 0, 0},
|
||||
};
|
||||
|
||||
static int mmhub_v1_0_get_ras_error_count(const struct soc15_reg_entry *reg,
|
||||
uint32_t value, uint32_t *sec_count, uint32_t *ded_count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t sec_cnt, ded_cnt;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mmhub_v1_0_ras_fields); i++) {
|
||||
if(mmhub_v1_0_ras_fields[i].reg_offset != reg->reg_offset)
|
||||
continue;
|
||||
|
||||
sec_cnt = (value &
|
||||
mmhub_v1_0_ras_fields[i].sec_count_mask) >>
|
||||
mmhub_v1_0_ras_fields[i].sec_count_shift;
|
||||
if (sec_cnt) {
|
||||
DRM_INFO("MMHUB SubBlock %s, SEC %d\n",
|
||||
mmhub_v1_0_ras_fields[i].name,
|
||||
sec_cnt);
|
||||
*sec_count += sec_cnt;
|
||||
}
|
||||
|
||||
ded_cnt = (value &
|
||||
mmhub_v1_0_ras_fields[i].ded_count_mask) >>
|
||||
mmhub_v1_0_ras_fields[i].ded_count_shift;
|
||||
if (ded_cnt) {
|
||||
DRM_INFO("MMHUB SubBlock %s, DED %d\n",
|
||||
mmhub_v1_0_ras_fields[i].name,
|
||||
ded_cnt);
|
||||
*ded_count += ded_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmhub_v1_0_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
int i;
|
||||
uint32_t ea0_edc_cnt, ea0_edc_cnt2;
|
||||
uint32_t ea1_edc_cnt, ea1_edc_cnt2;
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
uint32_t sec_count = 0, ded_count = 0;
|
||||
uint32_t i;
|
||||
uint32_t reg_value;
|
||||
|
||||
/* EDC CNT will be cleared automatically after read */
|
||||
ea0_edc_cnt = RREG32_SOC15(MMHUB, 0, mmMMEA0_EDC_CNT_VG20);
|
||||
ea0_edc_cnt2 = RREG32_SOC15(MMHUB, 0, mmMMEA0_EDC_CNT2_VG20);
|
||||
ea1_edc_cnt = RREG32_SOC15(MMHUB, 0, mmMMEA1_EDC_CNT_VG20);
|
||||
ea1_edc_cnt2 = RREG32_SOC15(MMHUB, 0, mmMMEA1_EDC_CNT2_VG20);
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
|
||||
/* error count of each error type is recorded by 2 bits,
|
||||
* ce and ue count in EDC_CNT
|
||||
*/
|
||||
for (i = 0; i < 5; i++) {
|
||||
err_data->ce_count += (ea0_edc_cnt & EA_EDC_CNT_MASK);
|
||||
err_data->ce_count += (ea1_edc_cnt & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
err_data->ue_count += (ea0_edc_cnt & EA_EDC_CNT_MASK);
|
||||
err_data->ue_count += (ea1_edc_cnt & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
}
|
||||
/* successive ue count in EDC_CNT */
|
||||
for (i = 0; i < 5; i++) {
|
||||
err_data->ue_count += (ea0_edc_cnt & EA_EDC_CNT_MASK);
|
||||
err_data->ue_count += (ea1_edc_cnt & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt >>= EA_EDC_CNT_SHIFT;
|
||||
for (i = 0; i < ARRAY_SIZE(mmhub_v1_0_edc_cnt_regs); i++) {
|
||||
reg_value =
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(mmhub_v1_0_edc_cnt_regs[i]));
|
||||
if (reg_value)
|
||||
mmhub_v1_0_get_ras_error_count(&mmhub_v1_0_edc_cnt_regs[i],
|
||||
reg_value, &sec_count, &ded_count);
|
||||
}
|
||||
|
||||
/* ce and ue count in EDC_CNT2 */
|
||||
for (i = 0; i < 3; i++) {
|
||||
err_data->ce_count += (ea0_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
err_data->ce_count += (ea1_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
err_data->ue_count += (ea0_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
err_data->ue_count += (ea1_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
}
|
||||
/* successive ue count in EDC_CNT2 */
|
||||
for (i = 0; i < 6; i++) {
|
||||
err_data->ue_count += (ea0_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
err_data->ue_count += (ea1_edc_cnt2 & EA_EDC_CNT_MASK);
|
||||
ea0_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
ea1_edc_cnt2 >>= EA_EDC_CNT_SHIFT;
|
||||
}
|
||||
err_data->ce_count += sec_count;
|
||||
err_data->ue_count += ded_count;
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = {
|
||||
|
@ -21,6 +21,7 @@
|
||||
*
|
||||
*/
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "mmhub_v9_4.h"
|
||||
|
||||
#include "mmhub/mmhub_9_4_1_offset.h"
|
||||
@ -29,7 +30,7 @@
|
||||
#include "athub/athub_1_0_offset.h"
|
||||
#include "athub/athub_1_0_sh_mask.h"
|
||||
#include "vega10_enum.h"
|
||||
|
||||
#include "soc15.h"
|
||||
#include "soc15_common.h"
|
||||
|
||||
#define MMHUB_NUM_INSTANCES 2
|
||||
@ -53,7 +54,7 @@ u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev)
|
||||
return base;
|
||||
}
|
||||
|
||||
void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, int hubid,
|
||||
static void mmhub_v9_4_setup_hubid_vm_pt_regs(struct amdgpu_device *adev, int hubid,
|
||||
uint32_t vmid, uint64_t value)
|
||||
{
|
||||
/* two registers distance between mmVML2VC0_VM_CONTEXT0_* to
|
||||
@ -79,7 +80,7 @@ static void mmhub_v9_4_init_gart_aperture_regs(struct amdgpu_device *adev,
|
||||
{
|
||||
uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
|
||||
|
||||
mmhub_v9_4_setup_vm_pt_regs(adev, hubid, 0, pt_base);
|
||||
mmhub_v9_4_setup_hubid_vm_pt_regs(adev, hubid, 0, pt_base);
|
||||
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0,
|
||||
mmVML2VC0_VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
|
||||
@ -100,6 +101,16 @@ static void mmhub_v9_4_init_gart_aperture_regs(struct amdgpu_device *adev,
|
||||
(u32)(adev->gmc.gart_end >> 44));
|
||||
}
|
||||
|
||||
void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint64_t page_table_base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MMHUB_NUM_INSTANCES; i++)
|
||||
mmhub_v9_4_setup_hubid_vm_pt_regs(adev, i, vmid,
|
||||
page_table_base);
|
||||
}
|
||||
|
||||
static void mmhub_v9_4_init_system_aperture_regs(struct amdgpu_device *adev,
|
||||
int hubid)
|
||||
{
|
||||
@ -313,7 +324,8 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
|
||||
adev->vm_manager.block_size - 9);
|
||||
/* Send no-retry XNACK on fault to suppress VM fault storm. */
|
||||
tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
|
||||
RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
|
||||
!amdgpu_noretry);
|
||||
WREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT1_CNTL,
|
||||
hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i,
|
||||
tmp);
|
||||
@ -655,3 +667,253 @@ void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
if (data & ATCL2_0_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK)
|
||||
*flags |= AMD_CG_SUPPORT_MC_LS;
|
||||
}
|
||||
|
||||
static const struct soc15_ras_field_entry mmhub_v9_4_ras_fields[] = {
|
||||
{ "MMEA0_DRAMRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_RRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, RRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, RRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_WRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, WRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, WRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, DRAMWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, IORD_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, IOWR_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT, IOWR_DATAMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_GMIRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT2, GMIWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA0_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, DRAMRD_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, DRAMWR_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, IORD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, IOWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, IOWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, GMIRD_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA0_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA0_EDC_CNT3, GMIWR_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_RRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, RRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, RRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_WRET_TAGMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, WRET_TAGMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, WRET_TAGMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, DRAMWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, IORD_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, IOWR_CMDMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT, IOWR_DATAMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_GMIRD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIRD_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIRD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIWR_CMDMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIWR_DATAMEM_SEC_COUNT),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIRD_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2),
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT2, GMIWR_PAGEMEM_SED_COUNT),
|
||||
0, 0,
|
||||
},
|
||||
{ "MMEA1_DRAMRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, DRAMRD_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_DRAMWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, DRAMWR_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_IORD_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, IORD_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_IOWR_CMDMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, IOWR_CMDMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_IOWR_DATAMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, IOWR_DATAMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIRD_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, GMIRD_PAGEMEM_DED_COUNT),
|
||||
},
|
||||
{ "MMEA1_GMIWR_PAGEMEM", SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3),
|
||||
0, 0,
|
||||
SOC15_REG_FIELD(MMEA1_EDC_CNT3, GMIWR_PAGEMEM_DED_COUNT),
|
||||
}
|
||||
};
|
||||
|
||||
static const struct soc15_reg_entry mmhub_v9_4_edc_cnt_regs[] = {
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT2), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_EDC_CNT3), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT2), 0, 0, 0},
|
||||
{ SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_EDC_CNT3), 0, 0, 0},
|
||||
};
|
||||
|
||||
static int mmhub_v9_4_get_ras_error_count(const struct soc15_reg_entry *reg,
|
||||
uint32_t value, uint32_t *sec_count, uint32_t *ded_count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t sec_cnt, ded_cnt;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mmhub_v9_4_ras_fields); i++) {
|
||||
if(mmhub_v9_4_ras_fields[i].reg_offset != reg->reg_offset)
|
||||
continue;
|
||||
|
||||
sec_cnt = (value &
|
||||
mmhub_v9_4_ras_fields[i].sec_count_mask) >>
|
||||
mmhub_v9_4_ras_fields[i].sec_count_shift;
|
||||
if (sec_cnt) {
|
||||
DRM_INFO("MMHUB SubBlock %s, SEC %d\n",
|
||||
mmhub_v9_4_ras_fields[i].name,
|
||||
sec_cnt);
|
||||
*sec_count += sec_cnt;
|
||||
}
|
||||
|
||||
ded_cnt = (value &
|
||||
mmhub_v9_4_ras_fields[i].ded_count_mask) >>
|
||||
mmhub_v9_4_ras_fields[i].ded_count_shift;
|
||||
if (ded_cnt) {
|
||||
DRM_INFO("MMHUB SubBlock %s, DED %d\n",
|
||||
mmhub_v9_4_ras_fields[i].name,
|
||||
ded_cnt);
|
||||
*ded_count += ded_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmhub_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
uint32_t sec_count = 0, ded_count = 0;
|
||||
uint32_t i;
|
||||
uint32_t reg_value;
|
||||
|
||||
err_data->ue_count = 0;
|
||||
err_data->ce_count = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mmhub_v9_4_edc_cnt_regs); i++) {
|
||||
reg_value =
|
||||
RREG32(SOC15_REG_ENTRY_OFFSET(mmhub_v9_4_edc_cnt_regs[i]));
|
||||
if (reg_value)
|
||||
mmhub_v9_4_get_ras_error_count(&mmhub_v9_4_edc_cnt_regs[i],
|
||||
reg_value, &sec_count, &ded_count);
|
||||
}
|
||||
|
||||
err_data->ce_count += sec_count;
|
||||
err_data->ue_count += ded_count;
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.query_ras_error_count = mmhub_v9_4_query_ras_error_count,
|
||||
};
|
||||
|
@ -23,6 +23,8 @@
|
||||
#ifndef __MMHUB_V9_4_H__
|
||||
#define __MMHUB_V9_4_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs;
|
||||
|
||||
u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev);
|
||||
int mmhub_v9_4_gart_enable(struct amdgpu_device *adev);
|
||||
void mmhub_v9_4_gart_disable(struct amdgpu_device *adev);
|
||||
@ -32,5 +34,7 @@ void mmhub_v9_4_init(struct amdgpu_device *adev);
|
||||
int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state);
|
||||
void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags);
|
||||
void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
|
||||
uint64_t page_table_base);
|
||||
|
||||
#endif
|
||||
|
@ -158,82 +158,6 @@ static void xgpu_ai_mailbox_trans_msg (struct amdgpu_device *adev,
|
||||
xgpu_ai_mailbox_set_valid(adev, false);
|
||||
}
|
||||
|
||||
static int xgpu_ai_get_pp_clk(struct amdgpu_device *adev, u32 type, char *buf)
|
||||
{
|
||||
int r = 0;
|
||||
u32 req, val, size;
|
||||
|
||||
if (!amdgim_is_hwperf(adev) || buf == NULL)
|
||||
return -EBADRQC;
|
||||
|
||||
switch(type) {
|
||||
case PP_SCLK:
|
||||
req = IDH_IRQ_GET_PP_SCLK;
|
||||
break;
|
||||
case PP_MCLK:
|
||||
req = IDH_IRQ_GET_PP_MCLK;
|
||||
break;
|
||||
default:
|
||||
return -EBADRQC;
|
||||
}
|
||||
|
||||
mutex_lock(&adev->virt.dpm_mutex);
|
||||
|
||||
xgpu_ai_mailbox_trans_msg(adev, req, 0, 0, 0);
|
||||
|
||||
r = xgpu_ai_poll_msg(adev, IDH_SUCCESS);
|
||||
if (!r && adev->fw_vram_usage.va != NULL) {
|
||||
val = RREG32_NO_KIQ(
|
||||
SOC15_REG_OFFSET(NBIO, 0,
|
||||
mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW1));
|
||||
size = strnlen((((char *)adev->virt.fw_reserve.p_pf2vf) +
|
||||
val), PAGE_SIZE);
|
||||
|
||||
if (size < PAGE_SIZE)
|
||||
strcpy(buf,((char *)adev->virt.fw_reserve.p_pf2vf + val));
|
||||
else
|
||||
size = 0;
|
||||
|
||||
r = size;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = xgpu_ai_poll_msg(adev, IDH_FAIL);
|
||||
if(r)
|
||||
pr_info("%s DPM request failed",
|
||||
(type == PP_SCLK)? "SCLK" : "MCLK");
|
||||
|
||||
out:
|
||||
mutex_unlock(&adev->virt.dpm_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int xgpu_ai_force_dpm_level(struct amdgpu_device *adev, u32 level)
|
||||
{
|
||||
int r = 0;
|
||||
u32 req = IDH_IRQ_FORCE_DPM_LEVEL;
|
||||
|
||||
if (!amdgim_is_hwperf(adev))
|
||||
return -EBADRQC;
|
||||
|
||||
mutex_lock(&adev->virt.dpm_mutex);
|
||||
xgpu_ai_mailbox_trans_msg(adev, req, level, 0, 0);
|
||||
|
||||
r = xgpu_ai_poll_msg(adev, IDH_SUCCESS);
|
||||
if (!r)
|
||||
goto out;
|
||||
|
||||
r = xgpu_ai_poll_msg(adev, IDH_FAIL);
|
||||
if (!r)
|
||||
pr_info("DPM request failed");
|
||||
else
|
||||
pr_info("Mailbox is broken");
|
||||
|
||||
out:
|
||||
mutex_unlock(&adev->virt.dpm_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
|
||||
enum idh_request req)
|
||||
{
|
||||
@ -455,6 +379,4 @@ const struct amdgpu_virt_ops xgpu_ai_virt_ops = {
|
||||
.reset_gpu = xgpu_ai_request_reset,
|
||||
.wait_reset = NULL,
|
||||
.trans_msg = xgpu_ai_mailbox_trans_msg,
|
||||
.get_pp_clk = xgpu_ai_get_pp_clk,
|
||||
.force_dpm_level = xgpu_ai_force_dpm_level,
|
||||
};
|
||||
|
@ -35,10 +35,6 @@ enum idh_request {
|
||||
IDH_REL_GPU_FINI_ACCESS,
|
||||
IDH_REQ_GPU_RESET_ACCESS,
|
||||
|
||||
IDH_IRQ_FORCE_DPM_LEVEL = 10,
|
||||
IDH_IRQ_GET_PP_SCLK,
|
||||
IDH_IRQ_GET_PP_MCLK,
|
||||
|
||||
IDH_LOG_VF_ERROR = 200,
|
||||
};
|
||||
|
||||
|
@ -52,6 +52,9 @@
|
||||
#define BIF_MMSCH1_DOORBELL_RANGE__OFFSET_MASK 0x00000FFCL
|
||||
#define BIF_MMSCH1_DOORBELL_RANGE__SIZE_MASK 0x001F0000L
|
||||
|
||||
static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
|
||||
static void nbio_v7_4_remap_hdp_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
WREG32_SOC15(NBIO, 0, mmREMAP_HDP_MEM_FLUSH_CNTL,
|
||||
@ -314,6 +317,7 @@ static void nbio_v7_4_init_registers(struct amdgpu_device *adev)
|
||||
static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t bif_doorbell_intr_cntl;
|
||||
struct ras_manager *obj = amdgpu_ras_find_obj(adev, adev->nbio.ras_if);
|
||||
|
||||
bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
|
||||
if (REG_GET_FIELD(bif_doorbell_intr_cntl,
|
||||
@ -324,7 +328,18 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device
|
||||
RAS_CNTLR_INTERRUPT_CLEAR, 1);
|
||||
WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
|
||||
|
||||
amdgpu_ras_global_ras_isr(adev);
|
||||
/*
|
||||
* clear error status after ras_controller_intr according to
|
||||
* hw team and count ue number for query
|
||||
*/
|
||||
nbio_v7_4_query_ras_error_count(adev, &obj->err_data);
|
||||
|
||||
DRM_WARN("RAS controller interrupt triggered by NBIF error\n");
|
||||
|
||||
/* ras_controller_int is dedicated for nbif ras error,
|
||||
* not the global interrupt for sync flood
|
||||
*/
|
||||
amdgpu_ras_reset_gpu(adev, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -467,10 +482,12 @@ static int nbio_v7_4_init_ras_err_event_athub_interrupt (struct amdgpu_device *a
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define smnPARITY_ERROR_STATUS_UNCORR_GRP2 0x13a20030
|
||||
|
||||
static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
uint32_t global_sts, central_sts, int_eoi;
|
||||
uint32_t global_sts, central_sts, int_eoi, parity_sts;
|
||||
uint32_t corr, fatal, non_fatal;
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
||||
@ -479,6 +496,7 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrFatal);
|
||||
non_fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO,
|
||||
ParityErrNonFatal);
|
||||
parity_sts = RREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2);
|
||||
|
||||
if (corr)
|
||||
err_data->ce_count++;
|
||||
@ -490,6 +508,11 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
/* clear error status register */
|
||||
WREG32_PCIE(smnRAS_GLOBAL_STATUS_LO, global_sts);
|
||||
|
||||
if (fatal)
|
||||
/* clear parity fatal error indication field */
|
||||
WREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2,
|
||||
parity_sts);
|
||||
|
||||
if (REG_GET_FIELD(central_sts, BIFL_RAS_CENTRAL_STATUS,
|
||||
BIFL_RasContller_Intr_Recv)) {
|
||||
/* clear interrupt status register */
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "gfx_v10_0.h"
|
||||
#include "sdma_v5_0.h"
|
||||
#include "vcn_v2_0.h"
|
||||
#include "jpeg_v2_0.h"
|
||||
#include "dce_virtual.h"
|
||||
#include "mes_v10_1.h"
|
||||
#include "mxgpu_nv.h"
|
||||
@ -314,6 +315,16 @@ static int nv_asic_mode1_reset(struct amdgpu_device *adev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool nv_asic_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
if (smu_baco_is_support(smu))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
nv_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -342,7 +353,12 @@ static int nv_asic_reset(struct amdgpu_device *adev)
|
||||
if (nv_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
|
||||
if (!adev->in_suspend)
|
||||
amdgpu_inc_vram_lost(adev);
|
||||
ret = smu_baco_reset(smu);
|
||||
ret = smu_baco_enter(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = smu_baco_exit(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (!adev->in_suspend)
|
||||
amdgpu_inc_vram_lost(adev);
|
||||
@ -476,6 +492,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
|
||||
is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
if (adev->enable_mes)
|
||||
amdgpu_device_ip_block_add(adev, &mes_v10_1_ip_block);
|
||||
break;
|
||||
@ -499,6 +516,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
|
||||
is_support_sw_smu(adev) && !amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -617,6 +635,7 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
|
||||
.get_pcie_usage = &nv_get_pcie_usage,
|
||||
.need_reset_on_init = &nv_need_reset_on_init,
|
||||
.get_pcie_replay_count = &nv_get_pcie_replay_count,
|
||||
.supports_baco = &nv_asic_supports_baco,
|
||||
};
|
||||
|
||||
static int nv_common_early_init(void *handle)
|
||||
@ -656,10 +675,12 @@ static int nv_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_ATHUB_MGCG |
|
||||
AMD_CG_SUPPORT_ATHUB_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_LS;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_ATHUB;
|
||||
adev->external_rev_id = adev->rev_id + 0x1;
|
||||
break;
|
||||
@ -676,9 +697,11 @@ static int nv_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_ATHUB_MGCG |
|
||||
AMD_CG_SUPPORT_ATHUB_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_MGCG |
|
||||
AMD_CG_SUPPORT_BIF_LS;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->external_rev_id = adev->rev_id + 20;
|
||||
break;
|
||||
@ -697,9 +720,11 @@ static int nv_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_MC_LS |
|
||||
AMD_CG_SUPPORT_ATHUB_MGCG |
|
||||
AMD_CG_SUPPORT_ATHUB_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG;
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_ATHUB;
|
||||
adev->external_rev_id = adev->rev_id + 0xa;
|
||||
break;
|
||||
|
@ -230,54 +230,6 @@ static int psp_v10_0_ring_destroy(struct psp_context *psp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v10_0_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int psp_write_ptr_reg = 0;
|
||||
struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
|
||||
struct psp_ring *ring = &psp->km_ring;
|
||||
struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
|
||||
struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
|
||||
ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
uint32_t ring_size_dw = ring->ring_size / 4;
|
||||
uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
|
||||
|
||||
/* KM (GPCOM) prepare write pointer */
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
/* Update KM RB frame pointer to new frame */
|
||||
if ((psp_write_ptr_reg % ring_size_dw) == 0)
|
||||
write_frame = ring_buffer_start;
|
||||
else
|
||||
write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
|
||||
/* Check invalid write_frame ptr address */
|
||||
if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
|
||||
DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
|
||||
ring_buffer_start, ring_buffer_end, write_frame);
|
||||
DRM_ERROR("write_frame is pointing to address out of bounds\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize KM RB frame */
|
||||
memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
|
||||
|
||||
/* Update KM RB frame */
|
||||
write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
|
||||
write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
|
||||
write_frame->fence_value = index;
|
||||
amdgpu_asic_flush_hdp(adev, NULL);
|
||||
|
||||
/* Update the write Pointer in DWORDs */
|
||||
psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
psp_v10_0_sram_map(struct amdgpu_device *adev,
|
||||
unsigned int *sram_offset, unsigned int *sram_addr_reg_offset,
|
||||
@ -407,15 +359,30 @@ static int psp_v10_0_mode1_reset(struct psp_context *psp)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static uint32_t psp_v10_0_ring_get_wptr(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
return RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
}
|
||||
|
||||
static void psp_v10_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
|
||||
}
|
||||
|
||||
static const struct psp_funcs psp_v10_0_funcs = {
|
||||
.init_microcode = psp_v10_0_init_microcode,
|
||||
.ring_init = psp_v10_0_ring_init,
|
||||
.ring_create = psp_v10_0_ring_create,
|
||||
.ring_stop = psp_v10_0_ring_stop,
|
||||
.ring_destroy = psp_v10_0_ring_destroy,
|
||||
.cmd_submit = psp_v10_0_cmd_submit,
|
||||
.compare_sram_data = psp_v10_0_compare_sram_data,
|
||||
.mode1_reset = psp_v10_0_mode1_reset,
|
||||
.ring_get_wptr = psp_v10_0_ring_get_wptr,
|
||||
.ring_set_wptr = psp_v10_0_ring_set_wptr,
|
||||
};
|
||||
|
||||
void psp_v10_0_set_psp_funcs(struct psp_context *psp)
|
||||
|
@ -186,6 +186,31 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
case CHIP_NAVI12:
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
|
||||
err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
|
||||
if (err) {
|
||||
release_firmware(adev->psp.ta_fw);
|
||||
adev->psp.ta_fw = NULL;
|
||||
dev_info(adev->dev,
|
||||
"psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
|
||||
} else {
|
||||
err = amdgpu_ucode_validate(adev->psp.ta_fw);
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.ta_hdcp_ucode_version = le32_to_cpu(ta_hdr->ta_hdcp_ucode_version);
|
||||
adev->psp.ta_hdcp_ucode_size = le32_to_cpu(ta_hdr->ta_hdcp_size_bytes);
|
||||
adev->psp.ta_hdcp_start_addr = (uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.ta_dtm_ucode_version = le32_to_cpu(ta_hdr->ta_dtm_ucode_version);
|
||||
adev->psp.ta_dtm_ucode_size = le32_to_cpu(ta_hdr->ta_dtm_size_bytes);
|
||||
adev->psp.ta_dtm_start_addr = (uint8_t *)adev->psp.ta_hdcp_start_addr +
|
||||
le32_to_cpu(ta_hdr->ta_dtm_offset_bytes);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
@ -519,63 +544,6 @@ static int psp_v11_0_ring_destroy(struct psp_context *psp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v11_0_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int psp_write_ptr_reg = 0;
|
||||
struct psp_gfx_rb_frame *write_frame = psp->km_ring.ring_mem;
|
||||
struct psp_ring *ring = &psp->km_ring;
|
||||
struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
|
||||
struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
|
||||
ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
uint32_t ring_size_dw = ring->ring_size / 4;
|
||||
uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
|
||||
|
||||
/* KM (GPCOM) prepare write pointer */
|
||||
if (psp_v11_0_support_vmr_ring(psp))
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
/* Update KM RB frame pointer to new frame */
|
||||
/* write_frame ptr increments by size of rb_frame in bytes */
|
||||
/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
|
||||
if ((psp_write_ptr_reg % ring_size_dw) == 0)
|
||||
write_frame = ring_buffer_start;
|
||||
else
|
||||
write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
|
||||
/* Check invalid write_frame ptr address */
|
||||
if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
|
||||
DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
|
||||
ring_buffer_start, ring_buffer_end, write_frame);
|
||||
DRM_ERROR("write_frame is pointing to address out of bounds\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize KM RB frame */
|
||||
memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
|
||||
|
||||
/* Update KM RB frame */
|
||||
write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
|
||||
write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
|
||||
write_frame->fence_value = index;
|
||||
amdgpu_asic_flush_hdp(adev, NULL);
|
||||
|
||||
/* Update the write Pointer in DWORDs */
|
||||
psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
|
||||
if (psp_v11_0_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg);
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
psp_v11_0_sram_map(struct amdgpu_device *adev,
|
||||
unsigned int *sram_offset, unsigned int *sram_addr_reg_offset,
|
||||
@ -1068,6 +1036,30 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t psp_v11_0_ring_get_wptr(struct psp_context *psp)
|
||||
{
|
||||
uint32_t data;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v11_0_support_vmr_ring(psp))
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v11_0_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
|
||||
}
|
||||
|
||||
static const struct psp_funcs psp_v11_0_funcs = {
|
||||
.init_microcode = psp_v11_0_init_microcode,
|
||||
.bootloader_load_kdb = psp_v11_0_bootloader_load_kdb,
|
||||
@ -1077,7 +1069,6 @@ static const struct psp_funcs psp_v11_0_funcs = {
|
||||
.ring_create = psp_v11_0_ring_create,
|
||||
.ring_stop = psp_v11_0_ring_stop,
|
||||
.ring_destroy = psp_v11_0_ring_destroy,
|
||||
.cmd_submit = psp_v11_0_cmd_submit,
|
||||
.compare_sram_data = psp_v11_0_compare_sram_data,
|
||||
.mode1_reset = psp_v11_0_mode1_reset,
|
||||
.xgmi_get_topology_info = psp_v11_0_xgmi_get_topology_info,
|
||||
@ -1091,6 +1082,8 @@ static const struct psp_funcs psp_v11_0_funcs = {
|
||||
.mem_training_init = psp_v11_0_memory_training_init,
|
||||
.mem_training_fini = psp_v11_0_memory_training_fini,
|
||||
.mem_training = psp_v11_0_memory_training,
|
||||
.ring_get_wptr = psp_v11_0_ring_get_wptr,
|
||||
.ring_set_wptr = psp_v11_0_ring_set_wptr,
|
||||
};
|
||||
|
||||
void psp_v11_0_set_psp_funcs(struct psp_context *psp)
|
||||
|
@ -334,63 +334,6 @@ static int psp_v12_0_ring_destroy(struct psp_context *psp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v12_0_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int psp_write_ptr_reg = 0;
|
||||
struct psp_gfx_rb_frame *write_frame = psp->km_ring.ring_mem;
|
||||
struct psp_ring *ring = &psp->km_ring;
|
||||
struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
|
||||
struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
|
||||
ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
uint32_t ring_size_dw = ring->ring_size / 4;
|
||||
uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
|
||||
|
||||
/* KM (GPCOM) prepare write pointer */
|
||||
if (psp_v12_0_support_vmr_ring(psp))
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
/* Update KM RB frame pointer to new frame */
|
||||
/* write_frame ptr increments by size of rb_frame in bytes */
|
||||
/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
|
||||
if ((psp_write_ptr_reg % ring_size_dw) == 0)
|
||||
write_frame = ring_buffer_start;
|
||||
else
|
||||
write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
|
||||
/* Check invalid write_frame ptr address */
|
||||
if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
|
||||
DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
|
||||
ring_buffer_start, ring_buffer_end, write_frame);
|
||||
DRM_ERROR("write_frame is pointing to address out of bounds\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize KM RB frame */
|
||||
memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
|
||||
|
||||
/* Update KM RB frame */
|
||||
write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
|
||||
write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
|
||||
write_frame->fence_value = index;
|
||||
amdgpu_asic_flush_hdp(adev, NULL);
|
||||
|
||||
/* Update the write Pointer in DWORDs */
|
||||
psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
|
||||
if (psp_v12_0_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg);
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
psp_v12_0_sram_map(struct amdgpu_device *adev,
|
||||
unsigned int *sram_offset, unsigned int *sram_addr_reg_offset,
|
||||
@ -547,6 +490,30 @@ static int psp_v12_0_mode1_reset(struct psp_context *psp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t psp_v12_0_ring_get_wptr(struct psp_context *psp)
|
||||
{
|
||||
uint32_t data;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v12_0_support_vmr_ring(psp))
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void psp_v12_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v12_0_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
|
||||
}
|
||||
|
||||
static const struct psp_funcs psp_v12_0_funcs = {
|
||||
.init_microcode = psp_v12_0_init_microcode,
|
||||
.bootloader_load_sysdrv = psp_v12_0_bootloader_load_sysdrv,
|
||||
@ -555,9 +522,10 @@ static const struct psp_funcs psp_v12_0_funcs = {
|
||||
.ring_create = psp_v12_0_ring_create,
|
||||
.ring_stop = psp_v12_0_ring_stop,
|
||||
.ring_destroy = psp_v12_0_ring_destroy,
|
||||
.cmd_submit = psp_v12_0_cmd_submit,
|
||||
.compare_sram_data = psp_v12_0_compare_sram_data,
|
||||
.mode1_reset = psp_v12_0_mode1_reset,
|
||||
.ring_get_wptr = psp_v12_0_ring_get_wptr,
|
||||
.ring_set_wptr = psp_v12_0_ring_set_wptr,
|
||||
};
|
||||
|
||||
void psp_v12_0_set_psp_funcs(struct psp_context *psp)
|
||||
|
@ -179,7 +179,7 @@ static bool psp_v3_1_match_version(struct amdgpu_device *adev, uint32_t ver)
|
||||
* Double check if the latest four legacy versions.
|
||||
* If yes, it is still the right version.
|
||||
*/
|
||||
for (i = 0; i < sizeof(sos_old_versions) / sizeof(uint32_t); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(sos_old_versions); i++) {
|
||||
if (sos_old_versions[i] == adev->psp.sos_fw_version)
|
||||
return true;
|
||||
}
|
||||
@ -410,65 +410,6 @@ static int psp_v3_1_ring_destroy(struct psp_context *psp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v3_1_cmd_submit(struct psp_context *psp,
|
||||
uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
|
||||
int index)
|
||||
{
|
||||
unsigned int psp_write_ptr_reg = 0;
|
||||
struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
|
||||
struct psp_ring *ring = &psp->km_ring;
|
||||
struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
|
||||
struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
|
||||
ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
uint32_t ring_size_dw = ring->ring_size / 4;
|
||||
uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
|
||||
|
||||
/* KM (GPCOM) prepare write pointer */
|
||||
if (psp_v3_1_support_vmr_ring(psp))
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
psp_write_ptr_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
|
||||
/* Update KM RB frame pointer to new frame */
|
||||
/* write_frame ptr increments by size of rb_frame in bytes */
|
||||
/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
|
||||
if ((psp_write_ptr_reg % ring_size_dw) == 0)
|
||||
write_frame = ring_buffer_start;
|
||||
else
|
||||
write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
|
||||
/* Check invalid write_frame ptr address */
|
||||
if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
|
||||
DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
|
||||
ring_buffer_start, ring_buffer_end, write_frame);
|
||||
DRM_ERROR("write_frame is pointing to address out of bounds\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialize KM RB frame */
|
||||
memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
|
||||
|
||||
/* Update KM RB frame */
|
||||
write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
|
||||
write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
|
||||
write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
|
||||
write_frame->fence_value = index;
|
||||
amdgpu_asic_flush_hdp(adev, NULL);
|
||||
|
||||
/* Update the write Pointer in DWORDs */
|
||||
psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
|
||||
if (psp_v3_1_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_write_ptr_reg);
|
||||
/* send interrupt to PSP for SRIOV ring write pointer update */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
|
||||
GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, psp_write_ptr_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
psp_v3_1_sram_map(struct amdgpu_device *adev,
|
||||
unsigned int *sram_offset, unsigned int *sram_addr_reg_offset,
|
||||
@ -642,6 +583,31 @@ static bool psp_v3_1_support_vmr_ring(struct psp_context *psp)
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t psp_v3_1_ring_get_wptr(struct psp_context *psp)
|
||||
{
|
||||
uint32_t data;
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v3_1_support_vmr_ring(psp))
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102);
|
||||
else
|
||||
data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void psp_v3_1_ring_set_wptr(struct psp_context *psp, uint32_t value)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
||||
if (psp_v3_1_support_vmr_ring(psp)) {
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value);
|
||||
/* send interrupt to PSP for SRIOV ring write pointer update */
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
|
||||
GFX_CTRL_CMD_ID_CONSUME_CMD);
|
||||
} else
|
||||
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value);
|
||||
}
|
||||
|
||||
static const struct psp_funcs psp_v3_1_funcs = {
|
||||
.init_microcode = psp_v3_1_init_microcode,
|
||||
.bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv,
|
||||
@ -650,11 +616,12 @@ static const struct psp_funcs psp_v3_1_funcs = {
|
||||
.ring_create = psp_v3_1_ring_create,
|
||||
.ring_stop = psp_v3_1_ring_stop,
|
||||
.ring_destroy = psp_v3_1_ring_destroy,
|
||||
.cmd_submit = psp_v3_1_cmd_submit,
|
||||
.compare_sram_data = psp_v3_1_compare_sram_data,
|
||||
.smu_reload_quirk = psp_v3_1_smu_reload_quirk,
|
||||
.mode1_reset = psp_v3_1_mode1_reset,
|
||||
.support_vmr_ring = psp_v3_1_support_vmr_ring,
|
||||
.ring_get_wptr = psp_v3_1_ring_get_wptr,
|
||||
.ring_set_wptr = psp_v3_1_ring_set_wptr,
|
||||
};
|
||||
|
||||
void psp_v3_1_set_psp_funcs(struct psp_context *psp)
|
||||
|
@ -1197,6 +1197,11 @@ static int si_asic_reset(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool si_asic_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
si_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -1425,6 +1430,7 @@ static const struct amdgpu_asic_funcs si_asic_funcs =
|
||||
.get_pcie_usage = &si_get_pcie_usage,
|
||||
.need_reset_on_init = &si_need_reset_on_init,
|
||||
.get_pcie_replay_count = &si_get_pcie_replay_count,
|
||||
.supports_baco = &si_asic_supports_baco,
|
||||
};
|
||||
|
||||
static uint32_t si_get_rev_id(struct amdgpu_device *adev)
|
||||
|
@ -67,7 +67,9 @@
|
||||
#include "vce_v4_0.h"
|
||||
#include "vcn_v1_0.h"
|
||||
#include "vcn_v2_0.h"
|
||||
#include "jpeg_v2_0.h"
|
||||
#include "vcn_v2_5.h"
|
||||
#include "jpeg_v2_5.h"
|
||||
#include "dce_virtual.h"
|
||||
#include "mxgpu_ai.h"
|
||||
#include "amdgpu_smu.h"
|
||||
@ -509,9 +511,15 @@ static int soc15_asic_baco_reset(struct amdgpu_device *adev)
|
||||
|
||||
if (is_support_sw_smu(adev)) {
|
||||
struct smu_context *smu = &adev->smu;
|
||||
int ret;
|
||||
|
||||
if (smu_baco_reset(smu))
|
||||
return -EIO;
|
||||
ret = smu_baco_enter(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = smu_baco_exit(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
@ -549,7 +557,8 @@ static int soc15_mode2_reset(struct amdgpu_device *adev)
|
||||
static enum amd_reset_method
|
||||
soc15_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
bool baco_reset;
|
||||
bool baco_reset = false;
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_RAVEN:
|
||||
@ -557,23 +566,21 @@ soc15_asic_reset_method(struct amdgpu_device *adev)
|
||||
return AMD_RESET_METHOD_MODE2;
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_ARCTURUS:
|
||||
soc15_asic_get_baco_capability(adev, &baco_reset);
|
||||
break;
|
||||
case CHIP_VEGA20:
|
||||
if (adev->psp.sos_fw_version >= 0x80067)
|
||||
soc15_asic_get_baco_capability(adev, &baco_reset);
|
||||
else
|
||||
baco_reset = false;
|
||||
if (baco_reset) {
|
||||
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0);
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
|
||||
if (hive || (ras && ras->supported))
|
||||
baco_reset = false;
|
||||
}
|
||||
/*
|
||||
* 1. PMFW version > 0x284300: all cases use baco
|
||||
* 2. PMFW version <= 0x284300: only sGPU w/o RAS use baco
|
||||
*/
|
||||
if ((ras && ras->supported) && adev->pm.fw_version <= 0x283400)
|
||||
baco_reset = false;
|
||||
break;
|
||||
default:
|
||||
baco_reset = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -599,6 +606,28 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
static bool soc15_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
bool baco_support;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
soc15_asic_get_baco_capability(adev, &baco_support);
|
||||
break;
|
||||
case CHIP_VEGA20:
|
||||
if (adev->psp.sos_fw_version >= 0x80067)
|
||||
soc15_asic_get_baco_capability(adev, &baco_support);
|
||||
else
|
||||
baco_support = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return baco_support;
|
||||
}
|
||||
|
||||
/*static int soc15_set_uvd_clock(struct amdgpu_device *adev, u32 clock,
|
||||
u32 cntl_reg, u32 status_reg)
|
||||
{
|
||||
@ -746,11 +775,11 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
||||
}
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (is_support_sw_smu(adev))
|
||||
if (is_support_sw_smu(adev)) {
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
} else {
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
}
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
@ -803,6 +832,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
||||
|
||||
if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT))
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_5_ip_block);
|
||||
break;
|
||||
case CHIP_RENOIR:
|
||||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
@ -821,6 +852,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
||||
amdgpu_device_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -999,6 +1031,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
|
||||
.get_pcie_usage = &soc15_get_pcie_usage,
|
||||
.need_reset_on_init = &soc15_need_reset_on_init,
|
||||
.get_pcie_replay_count = &soc15_get_pcie_replay_count,
|
||||
.supports_baco = &soc15_supports_baco,
|
||||
};
|
||||
|
||||
static const struct amdgpu_asic_funcs vega20_asic_funcs =
|
||||
@ -1007,6 +1040,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
|
||||
.read_bios_from_rom = &soc15_read_bios_from_rom,
|
||||
.read_register = &soc15_read_register,
|
||||
.reset = &soc15_asic_reset,
|
||||
.reset_method = &soc15_asic_reset_method,
|
||||
.set_vga_state = &soc15_vga_set_state,
|
||||
.get_xclk = &soc15_get_xclk,
|
||||
.set_uvd_clocks = &soc15_set_uvd_clocks,
|
||||
@ -1019,7 +1053,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
|
||||
.get_pcie_usage = &vega20_get_pcie_usage,
|
||||
.need_reset_on_init = &soc15_need_reset_on_init,
|
||||
.get_pcie_replay_count = &soc15_get_pcie_replay_count,
|
||||
.reset_method = &soc15_asic_reset_method
|
||||
.supports_baco = &soc15_supports_baco,
|
||||
};
|
||||
|
||||
static int soc15_common_early_init(void *handle)
|
||||
@ -1145,9 +1179,7 @@ static int soc15_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_SDMA_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG;
|
||||
|
||||
adev->pg_flags = AMD_PG_SUPPORT_SDMA |
|
||||
AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
|
||||
} else if (adev->pdev->device == 0x15d8) {
|
||||
adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
|
||||
AMD_CG_SUPPORT_GFX_MGLS |
|
||||
@ -1190,9 +1222,7 @@ static int soc15_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_SDMA_LS |
|
||||
AMD_CG_SUPPORT_VCN_MGCG;
|
||||
|
||||
adev->pg_flags = AMD_PG_SUPPORT_SDMA |
|
||||
AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
|
||||
}
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
@ -1208,7 +1238,9 @@ static int soc15_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_SDMA_LS |
|
||||
AMD_CG_SUPPORT_MC_MGCG |
|
||||
AMD_CG_SUPPORT_MC_LS |
|
||||
AMD_CG_SUPPORT_IH_CG;
|
||||
AMD_CG_SUPPORT_IH_CG |
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG;
|
||||
adev->pg_flags = 0;
|
||||
adev->external_rev_id = adev->rev_id + 0x32;
|
||||
break;
|
||||
@ -1229,12 +1261,14 @@ static int soc15_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_HDP_LS |
|
||||
AMD_CG_SUPPORT_ROM_MGCG |
|
||||
AMD_CG_SUPPORT_VCN_MGCG |
|
||||
AMD_CG_SUPPORT_JPEG_MGCG |
|
||||
AMD_CG_SUPPORT_IH_CG |
|
||||
AMD_CG_SUPPORT_ATHUB_LS |
|
||||
AMD_CG_SUPPORT_ATHUB_MGCG |
|
||||
AMD_CG_SUPPORT_DF_MGCG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_SDMA |
|
||||
AMD_PG_SUPPORT_VCN |
|
||||
AMD_PG_SUPPORT_JPEG |
|
||||
AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->external_rev_id = adev->rev_id + 0x91;
|
||||
break;
|
||||
|
@ -60,6 +60,18 @@ struct soc15_allowed_register_entry {
|
||||
bool grbm_indexed;
|
||||
};
|
||||
|
||||
struct soc15_ras_field_entry {
|
||||
const char *name;
|
||||
uint32_t hwip;
|
||||
uint32_t inst;
|
||||
uint32_t seg;
|
||||
uint32_t reg_offset;
|
||||
uint32_t sec_count_mask;
|
||||
uint32_t sec_count_shift;
|
||||
uint32_t ded_count_mask;
|
||||
uint32_t ded_count_shift;
|
||||
};
|
||||
|
||||
#define SOC15_REG_ENTRY(ip, inst, reg) ip##_HWIP, inst, reg##_BASE_IDX, reg
|
||||
|
||||
#define SOC15_REG_ENTRY_OFFSET(entry) (adev->reg_offset[entry.hwip][entry.inst][entry.seg] + entry.reg_offset)
|
||||
|
@ -52,6 +52,7 @@
|
||||
uint32_t old_ = 0; \
|
||||
uint32_t tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \
|
||||
uint32_t loop = adev->usec_timeout; \
|
||||
ret = 0; \
|
||||
while ((tmp_ & (mask)) != (expected_value)) { \
|
||||
if (old_ != tmp_) { \
|
||||
loop = adev->usec_timeout; \
|
||||
|
@ -31,6 +31,14 @@
|
||||
|
||||
#define smnMCA_UMC0_MCUMC_ADDRT0 0x50f10
|
||||
|
||||
/* UMC 6_1_2 register offsets */
|
||||
#define mmUMCCH0_0_EccErrCntSel_ARCT 0x0360
|
||||
#define mmUMCCH0_0_EccErrCntSel_ARCT_BASE_IDX 1
|
||||
#define mmUMCCH0_0_EccErrCnt_ARCT 0x0361
|
||||
#define mmUMCCH0_0_EccErrCnt_ARCT_BASE_IDX 1
|
||||
#define mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT 0x03c2
|
||||
#define mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT_BASE_IDX 1
|
||||
|
||||
/*
|
||||
* (addr / 256) * 8192, the higher 26 bits in ErrorAddr
|
||||
* is the index of 8KB block
|
||||
@ -95,12 +103,25 @@ static void umc_v6_1_query_correctable_error_count(struct amdgpu_device *adev,
|
||||
uint64_t mc_umc_status;
|
||||
uint32_t mc_umc_status_addr;
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
/* UMC 6_1_2 registers */
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel_ARCT);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt_ARCT);
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
|
||||
} else {
|
||||
/* UMC 6_1_1 registers */
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
}
|
||||
|
||||
/* select the lower chip and check the error count */
|
||||
ecc_err_cnt_sel = RREG32(ecc_err_cnt_sel_addr + umc_reg_offset);
|
||||
@ -141,8 +162,17 @@ static void umc_v6_1_querry_uncorrectable_error_count(struct amdgpu_device *adev
|
||||
uint64_t mc_umc_status;
|
||||
uint32_t mc_umc_status_addr;
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
/* UMC 6_1_2 registers */
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
|
||||
} else {
|
||||
/* UMC 6_1_1 registers */
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
}
|
||||
|
||||
/* check the MCUMC_STATUS */
|
||||
mc_umc_status = RREG64_UMC(mc_umc_status_addr + umc_reg_offset);
|
||||
@ -179,8 +209,17 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev,
|
||||
uint64_t mc_umc_status, err_addr, retired_page;
|
||||
struct eeprom_table_record *err_rec;
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
/* UMC 6_1_2 registers */
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0_ARCT);
|
||||
} else {
|
||||
/* UMC 6_1_1 registers */
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
}
|
||||
|
||||
/* skip error address process if -ENOMEM */
|
||||
if (!err_data->err_addr) {
|
||||
@ -241,10 +280,21 @@ static void umc_v6_1_err_cnt_init_per_channel(struct amdgpu_device *adev,
|
||||
uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
|
||||
uint32_t ecc_err_cnt_addr;
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
|
||||
if (adev->asic_type == CHIP_ARCTURUS) {
|
||||
/* UMC 6_1_2 registers */
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel_ARCT);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt_ARCT);
|
||||
} else {
|
||||
/* UMC 6_1_1 registers */
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_EccErrCnt);
|
||||
}
|
||||
|
||||
/* select the lower chip and check the error count */
|
||||
ecc_err_cnt_sel = RREG32(ecc_err_cnt_sel_addr + umc_reg_offset);
|
||||
|
@ -35,7 +35,8 @@
|
||||
/* total channel instances in one umc block */
|
||||
#define UMC_V6_1_TOTAL_CHANNEL_NUM (UMC_V6_1_CHANNEL_INSTANCE_NUM * UMC_V6_1_UMC_INSTANCE_NUM)
|
||||
/* UMC regiser per channel offset */
|
||||
#define UMC_V6_1_PER_CHANNEL_OFFSET 0x800
|
||||
#define UMC_V6_1_PER_CHANNEL_OFFSET_VG20 0x800
|
||||
#define UMC_V6_1_PER_CHANNEL_OFFSET_ARCT 0x400
|
||||
|
||||
/* EccErrCnt max value */
|
||||
#define UMC_V6_1_CE_CNT_MAX 0xffff
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "mmhub/mmhub_9_1_sh_mask.h"
|
||||
|
||||
#include "ivsrcid/vcn/irqsrcs_vcn_1_0.h"
|
||||
#include "jpeg_v1_0.h"
|
||||
|
||||
#define mmUVD_RBC_XX_IB_REG_CHECK 0x05ab
|
||||
#define mmUVD_RBC_XX_IB_REG_CHECK_BASE_IDX 1
|
||||
@ -45,9 +46,7 @@
|
||||
static int vcn_v1_0_stop(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr);
|
||||
static int vcn_v1_0_set_powergating_state(void *handle, enum amd_powergating_state state);
|
||||
static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
|
||||
struct dpg_pause_state *new_state);
|
||||
@ -68,9 +67,10 @@ static int vcn_v1_0_early_init(void *handle)
|
||||
|
||||
vcn_v1_0_set_dec_ring_funcs(adev);
|
||||
vcn_v1_0_set_enc_ring_funcs(adev);
|
||||
vcn_v1_0_set_jpeg_ring_funcs(adev);
|
||||
vcn_v1_0_set_irq_funcs(adev);
|
||||
|
||||
jpeg_v1_0_early_init(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -101,11 +101,6 @@ static int vcn_v1_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* VCN JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, 126, &adev->vcn.inst->irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_vcn_sw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
@ -149,17 +144,11 @@ static int vcn_v1_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
sprintf(ring->name, "vcn_jpeg");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->vcn.pause_dpg_mode = vcn_v1_0_pause_dpg_mode;
|
||||
adev->vcn.internal.jpeg_pitch = adev->vcn.inst->external.jpeg_pitch =
|
||||
SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_PITCH);
|
||||
|
||||
return 0;
|
||||
r = jpeg_v1_0_sw_init(handle);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,6 +167,8 @@ static int vcn_v1_0_sw_fini(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
jpeg_v1_0_sw_fini(handle);
|
||||
|
||||
r = amdgpu_vcn_sw_fini(adev);
|
||||
|
||||
return r;
|
||||
@ -207,7 +198,7 @@ static int vcn_v1_0_hw_init(void *handle)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
ring = &adev->jpeg.inst->ring_dec;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
@ -947,22 +938,7 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
|
||||
UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
|
||||
|
||||
/* initialize wptr */
|
||||
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
|
||||
/* copy patch commands to the jpeg ring */
|
||||
vcn_v1_0_jpeg_ring_set_patch_ring(ring,
|
||||
(ring->wptr + ring->max_dw * amdgpu_sched_hw_submission));
|
||||
jpeg_v1_0_start(adev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1106,13 +1082,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), 0,
|
||||
~UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK);
|
||||
|
||||
/* initialize JPEG wptr */
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
|
||||
/* copy patch commands to the jpeg ring */
|
||||
vcn_v1_0_jpeg_ring_set_patch_ring(ring,
|
||||
(ring->wptr + ring->max_dw * amdgpu_sched_hw_submission));
|
||||
jpeg_v1_0_start(adev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1316,7 +1286,7 @@ static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
|
||||
UVD_DPG_PAUSE__JPEG_PAUSE_DPG_ACK_MASK, ret_code);
|
||||
|
||||
/* Restore */
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
ring = &adev->jpeg.inst->ring_dec;
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
|
||||
UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
|
||||
@ -1716,389 +1686,6 @@ static void vcn_v1_0_enc_ring_emit_wreg(struct amdgpu_ring *ring,
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t vcn_v1_0_jpeg_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t vcn_v1_0_jpeg_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void vcn_v1_0_jpeg_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_insert_start - insert a start command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a start command to the ring.
|
||||
*/
|
||||
static void vcn_v1_0_jpeg_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_insert_end - insert a end command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a end command to the ring.
|
||||
*/
|
||||
static void vcn_v1_0_jpeg_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_emit_fence - emit an fence & trap command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @fence: fence to emit
|
||||
*
|
||||
* Write a fence and a trap command to the ring.
|
||||
*/
|
||||
static void vcn_v1_0_jpeg_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_GPCOM_DATA0), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_GPCOM_DATA1), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_GPCOM_CMD), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x8);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_GPCOM_CMD), 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0xffffffff);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x3fbc);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x1);
|
||||
|
||||
/* emit trap */
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v1_0_jpeg_ring_emit_ib - execute indirect buffer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @ib: indirect buffer to execute
|
||||
*
|
||||
* Write ring commands to execute the indirect buffer.
|
||||
*/
|
||||
static void vcn_v1_0_jpeg_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_IB_VMID), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JPEG_VMID), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_IB_SIZE), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, ib->length_dw);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_STATUS), 0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_emit_reg_wait(struct amdgpu_ring *ring,
|
||||
uint32_t reg, uint32_t val,
|
||||
uint32_t mask)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, val);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE3));
|
||||
}
|
||||
amdgpu_ring_write(ring, mask);
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||
uint32_t data0, data1, mask;
|
||||
|
||||
pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
|
||||
|
||||
/* wait for register write */
|
||||
data0 = hub->ctx0_ptb_addr_lo32 + vmid * 2;
|
||||
data1 = lower_32_bits(pd_addr);
|
||||
mask = 0xffffffff;
|
||||
vcn_v1_0_jpeg_ring_emit_reg_wait(ring, data0, data1, mask);
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_emit_wreg(struct amdgpu_ring *ring,
|
||||
uint32_t reg, uint32_t val)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0));
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ(0, 0, 0, PACKETJ_TYPE0));
|
||||
}
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
WARN_ON(ring->wptr % 2 || count % 2);
|
||||
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
ring->ring[(*ptr)++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[(*ptr)++] = 0;
|
||||
ring->ring[(*ptr)++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0);
|
||||
} else {
|
||||
ring->ring[(*ptr)++] = reg_offset;
|
||||
ring->ring[(*ptr)++] = PACKETJ(0, 0, 0, PACKETJ_TYPE0);
|
||||
}
|
||||
ring->ring[(*ptr)++] = val;
|
||||
}
|
||||
|
||||
static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
uint32_t reg, reg_offset, val, mask, i;
|
||||
|
||||
// 1st: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW);
|
||||
reg_offset = (reg << 2);
|
||||
val = lower_32_bits(ring->gpu_addr);
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 2nd: program mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH);
|
||||
reg_offset = (reg << 2);
|
||||
val = upper_32_bits(ring->gpu_addr);
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 3rd to 5th: issue MEM_READ commands
|
||||
for (i = 0; i <= 2; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE2);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
// 6th: program mmUVD_JRBC_RB_CNTL register to enable NO_FETCH and RPTR write ability
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x13;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 7th: program mmUVD_JRBC_RB_REF_DATA
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
// 8th: issue conditional register read mmUVD_JRBC_RB_CNTL
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x1;
|
||||
mask = 0x1;
|
||||
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_COND_RD_TIMER), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = 0x01400200;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_REF_DATA), 0, 0, PACKETJ_TYPE0);
|
||||
ring->ring[ptr++] = val;
|
||||
ring->ring[ptr++] = PACKETJ(SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_EXTERNAL_REG_BASE), 0, 0, PACKETJ_TYPE0);
|
||||
if (((reg_offset >= 0x1f800) && (reg_offset <= 0x21fff)) ||
|
||||
((reg_offset >= 0x1e000) && (reg_offset <= 0x1e1ff))) {
|
||||
ring->ring[ptr++] = 0;
|
||||
ring->ring[ptr++] = PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3);
|
||||
} else {
|
||||
ring->ring[ptr++] = reg_offset;
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE3);
|
||||
}
|
||||
ring->ring[ptr++] = mask;
|
||||
|
||||
//9th to 21st: insert no-op
|
||||
for (i = 0; i <= 12; i++) {
|
||||
ring->ring[ptr++] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
|
||||
ring->ring[ptr++] = 0;
|
||||
}
|
||||
|
||||
//22nd: reset mmUVD_JRBC_RB_RPTR
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_RPTR);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
|
||||
//23rd: program mmUVD_JRBC_RB_CNTL to disable no_fetch
|
||||
reg = SOC15_REG_OFFSET(UVD, 0, mmUVD_JRBC_RB_CNTL);
|
||||
reg_offset = (reg << 2);
|
||||
val = 0x12;
|
||||
vcn_v1_0_jpeg_ring_patch_wreg(ring, &ptr, reg_offset, val);
|
||||
}
|
||||
|
||||
static int vcn_v1_0_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
@ -2123,9 +1710,6 @@ static int vcn_v1_0_process_interrupt(struct amdgpu_device *adev,
|
||||
case 120:
|
||||
amdgpu_fence_process(&adev->vcn.inst->ring_enc[1]);
|
||||
break;
|
||||
case 126:
|
||||
amdgpu_fence_process(&adev->vcn.inst->ring_jpeg);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
@ -2259,41 +1843,6 @@ static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs vcn_v1_0_jpeg_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.nop = PACKET0(0x81ff, 0),
|
||||
.support_64bit_ptrs = false,
|
||||
.no_user_fence = true,
|
||||
.vmhub = AMDGPU_MMHUB_0,
|
||||
.extra_dw = 64,
|
||||
.get_rptr = vcn_v1_0_jpeg_ring_get_rptr,
|
||||
.get_wptr = vcn_v1_0_jpeg_ring_get_wptr,
|
||||
.set_wptr = vcn_v1_0_jpeg_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
6 + 6 + /* hdp invalidate / flush */
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* vcn_v1_0_jpeg_ring_emit_vm_flush */
|
||||
26 + 26 + /* vcn_v1_0_jpeg_ring_emit_fence x2 vm fence */
|
||||
6,
|
||||
.emit_ib_size = 22, /* vcn_v1_0_jpeg_ring_emit_ib */
|
||||
.emit_ib = vcn_v1_0_jpeg_ring_emit_ib,
|
||||
.emit_fence = vcn_v1_0_jpeg_ring_emit_fence,
|
||||
.emit_vm_flush = vcn_v1_0_jpeg_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_vcn_jpeg_ring_test_ring,
|
||||
.test_ib = amdgpu_vcn_jpeg_ring_test_ib,
|
||||
.insert_nop = vcn_v1_0_jpeg_ring_nop,
|
||||
.insert_start = vcn_v1_0_jpeg_ring_insert_start,
|
||||
.insert_end = vcn_v1_0_jpeg_ring_insert_end,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.begin_use = amdgpu_vcn_ring_begin_use,
|
||||
.end_use = amdgpu_vcn_ring_end_use,
|
||||
.emit_wreg = vcn_v1_0_jpeg_ring_emit_wreg,
|
||||
.emit_reg_wait = vcn_v1_0_jpeg_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void vcn_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_dec.funcs = &vcn_v1_0_dec_ring_vm_funcs;
|
||||
@ -2310,12 +1859,6 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
||||
DRM_INFO("VCN encode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_jpeg.funcs = &vcn_v1_0_jpeg_ring_vm_funcs;
|
||||
DRM_INFO("VCN jpeg decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs vcn_v1_0_irq_funcs = {
|
||||
.set = vcn_v1_0_set_interrupt_state,
|
||||
.process = vcn_v1_0_process_interrupt,
|
||||
|
@ -47,26 +47,6 @@
|
||||
#define mmUVD_LMI_RBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET 0x5a7
|
||||
#define mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET 0x1e2
|
||||
|
||||
#define mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET 0x1bfff
|
||||
#define mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET 0x4029
|
||||
#define mmUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET 0x402a
|
||||
#define mmUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET 0x402b
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40ea
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40eb
|
||||
#define mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET 0x40cf
|
||||
#define mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET 0x40d1
|
||||
#define mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40e8
|
||||
#define mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40e9
|
||||
#define mmUVD_JRBC_IB_SIZE_INTERNAL_OFFSET 0x4082
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET 0x40ec
|
||||
#define mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x40ed
|
||||
#define mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET 0x4085
|
||||
#define mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET 0x4084
|
||||
#define mmUVD_JRBC_STATUS_INTERNAL_OFFSET 0x4089
|
||||
#define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
|
||||
|
||||
#define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000
|
||||
|
||||
#define mmUVD_RBC_XX_IB_REG_CHECK 0x026b
|
||||
#define mmUVD_RBC_XX_IB_REG_CHECK_BASE_IDX 1
|
||||
#define mmUVD_REG_XX_MASK 0x026c
|
||||
@ -74,7 +54,6 @@
|
||||
|
||||
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_0_set_jpeg_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static int vcn_v2_0_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state);
|
||||
@ -97,7 +76,6 @@ static int vcn_v2_0_early_init(void *handle)
|
||||
|
||||
vcn_v2_0_set_dec_ring_funcs(adev);
|
||||
vcn_v2_0_set_enc_ring_funcs(adev);
|
||||
vcn_v2_0_set_jpeg_ring_funcs(adev);
|
||||
vcn_v2_0_set_irq_funcs(adev);
|
||||
|
||||
return 0;
|
||||
@ -132,12 +110,6 @@ static int vcn_v2_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* VCN JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
|
||||
VCN_2_0__SRCID__JPEG_DECODE, &adev->vcn.inst->irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_vcn_sw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
@ -194,19 +166,8 @@ static int vcn_v2_0_sw_init(void *handle)
|
||||
return r;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
|
||||
sprintf(ring->name, "vcn_jpeg");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->vcn.pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
|
||||
|
||||
adev->vcn.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
|
||||
adev->vcn.inst->external.jpeg_pitch = SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_PITCH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -258,11 +219,6 @@ static int vcn_v2_0_hw_init(void *handle)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
|
||||
@ -296,9 +252,6 @@ static int vcn_v2_0_hw_fini(void *handle)
|
||||
ring->sched.ready = false;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst->ring_jpeg;
|
||||
ring->sched.ready = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -393,7 +346,6 @@ static void vcn_v2_0_mc_resume(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
|
||||
|
||||
WREG32_SOC15(UVD, 0, mmUVD_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
|
||||
WREG32_SOC15(UVD, 0, mmJPEG_DEC_GFX10_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
|
||||
}
|
||||
|
||||
static void vcn_v2_0_mc_resume_dpg_mode(struct amdgpu_device *adev, bool indirect)
|
||||
@ -647,129 +599,6 @@ static void vcn_v2_0_clock_gating_dpg_mode(struct amdgpu_device *adev,
|
||||
UVD, 0, mmUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_start - start JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup and start the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring = &adev->vcn.inst->ring_jpeg;
|
||||
uint32_t tmp;
|
||||
int r = 0;
|
||||
|
||||
/* disable power gating */
|
||||
tmp = 1 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_PGFSM_CONFIG), tmp);
|
||||
|
||||
SOC15_WAIT_ON_RREG(VCN, 0,
|
||||
mmUVD_PGFSM_STATUS, UVD_PGFSM_STATUS_UVDJ_PWR_ON,
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK, r);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu: JPEG disable power gating failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Removing the anti hang mechanism to indicate the UVDJ tile is ON */
|
||||
tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_POWER_STATUS)) & ~0x1;
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_POWER_STATUS), tmp);
|
||||
|
||||
/* JPEG disable CGC */
|
||||
tmp = RREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL);
|
||||
tmp |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
tmp |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
tmp |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE);
|
||||
tmp &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
| JPEG_CGC_GATE__JMCIF_MASK
|
||||
| JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE, tmp);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
WREG32_P(SOC15_REG_OFFSET(VCN, 0, mmJPEG_SYS_INT_EN),
|
||||
JPEG_SYS_INT_EN__DJRBC_MASK,
|
||||
~JPEG_SYS_INT_EN__DJRBC_MASK);
|
||||
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_0_stop - stop JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* stop the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_0_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
int r = 0;
|
||||
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable JPEG CGC */
|
||||
tmp = RREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL);
|
||||
tmp |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
tmp |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
tmp |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(VCN, 0, mmJPEG_CGC_CTRL, tmp);
|
||||
|
||||
|
||||
tmp = RREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE);
|
||||
tmp |= (JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG_ENC_MASK
|
||||
|JPEG_CGC_GATE__JMCIF_MASK
|
||||
|JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(VCN, 0, mmJPEG_CGC_GATE, tmp);
|
||||
|
||||
/* enable power gating */
|
||||
tmp = RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_POWER_STATUS));
|
||||
tmp &= ~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK;
|
||||
tmp |= 0x1; //UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_TILES_OFF;
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_JPEG_POWER_STATUS), tmp);
|
||||
|
||||
tmp = 2 << UVD_PGFSM_CONFIG__UVDJ_PWR_CONFIG__SHIFT;
|
||||
WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_PGFSM_CONFIG), tmp);
|
||||
|
||||
SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_PGFSM_STATUS,
|
||||
(2 << UVD_PGFSM_STATUS__UVDJ_PWR_STATUS__SHIFT),
|
||||
UVD_PGFSM_STATUS__UVDJ_PWR_STATUS_MASK, r);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu: JPEG enable power gating failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_enable_clock_gating - enable VCN clock gating
|
||||
*
|
||||
@ -1052,12 +881,8 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_dpm_enable_uvd(adev, true);
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
|
||||
r = vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
|
||||
if (r)
|
||||
return r;
|
||||
goto jpeg;
|
||||
}
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
|
||||
return vcn_v2_0_start_dpg_mode(adev, adev->vcn.indirect_sram);
|
||||
|
||||
vcn_v2_0_disable_static_power_gating(adev);
|
||||
|
||||
@ -1209,10 +1034,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
|
||||
|
||||
jpeg:
|
||||
r = jpeg_v2_0_start(adev);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
|
||||
@ -1231,9 +1053,6 @@ static int vcn_v2_0_stop_dpg_mode(struct amdgpu_device *adev)
|
||||
tmp = RREG32_SOC15(UVD, 0, mmUVD_RB_WPTR2);
|
||||
SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_RB_RPTR2, tmp, 0xFFFFFFFF, ret_code);
|
||||
|
||||
tmp = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_JRBC_RB_RPTR, tmp, 0xFFFFFFFF, ret_code);
|
||||
|
||||
tmp = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR) & 0x7FFFFFFF;
|
||||
SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_RBC_RB_RPTR, tmp, 0xFFFFFFFF, ret_code);
|
||||
|
||||
@ -1252,10 +1071,6 @@ static int vcn_v2_0_stop(struct amdgpu_device *adev)
|
||||
uint32_t tmp;
|
||||
int r;
|
||||
|
||||
r = jpeg_v2_0_stop(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
|
||||
r = vcn_v2_0_stop_dpg_mode(adev);
|
||||
if (r)
|
||||
@ -1781,272 +1596,6 @@ void vcn_v2_0_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t vcn_v2_0_jpeg_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t vcn_v2_0_jpeg_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell)
|
||||
return adev->wb.wb[ring->wptr_offs];
|
||||
else
|
||||
return RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void vcn_v2_0_jpeg_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell) {
|
||||
adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
|
||||
WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
|
||||
} else {
|
||||
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_insert_start - insert a start command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a start command to the ring.
|
||||
*/
|
||||
void vcn_v2_0_jpeg_ring_insert_start(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x80010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_insert_end - insert a end command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Write a end command to the ring.
|
||||
*/
|
||||
void vcn_v2_0_jpeg_ring_insert_end(struct amdgpu_ring *ring)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x68e04);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x00010000);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_emit_fence - emit an fence & trap command
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @fence: fence to emit
|
||||
*
|
||||
* Write a fence and a trap command to the ring.
|
||||
*/
|
||||
void vcn_v2_0_jpeg_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags)
|
||||
{
|
||||
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA0_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_DATA1_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_WR_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x8);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_GPCOM_CMD_INTERNAL_OFFSET,
|
||||
0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE4));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x3fbc);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x1);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE7));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_0_jpeg_ring_emit_ib - execute indirect buffer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
* @ib: indirect buffer to execute
|
||||
*
|
||||
* Write ring commands to execute the indirect buffer.
|
||||
*/
|
||||
void vcn_v2_0_jpeg_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_IB_SIZE_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, ib->length_dw);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_RB_MEM_RD_64BIT_BAR_HIGH_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, upper_32_bits(ring->gpu_addr));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, PACKETJ_CONDITION_CHECK0, PACKETJ_TYPE2));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_STATUS_INTERNAL_OFFSET,
|
||||
0, PACKETJ_CONDITION_CHECK3, PACKETJ_TYPE3));
|
||||
amdgpu_ring_write(ring, 0x2);
|
||||
}
|
||||
|
||||
void vcn_v2_0_jpeg_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask)
|
||||
{
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_COND_RD_TIMER_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, 0x01400200);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, val);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE3));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE3));
|
||||
}
|
||||
amdgpu_ring_write(ring, mask);
|
||||
}
|
||||
|
||||
void vcn_v2_0_jpeg_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
|
||||
uint32_t data0, data1, mask;
|
||||
|
||||
pd_addr = amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
|
||||
|
||||
/* wait for register write */
|
||||
data0 = hub->ctx0_ptb_addr_lo32 + vmid * 2;
|
||||
data1 = lower_32_bits(pd_addr);
|
||||
mask = 0xffffffff;
|
||||
vcn_v2_0_jpeg_ring_emit_reg_wait(ring, data0, data1, mask);
|
||||
}
|
||||
|
||||
void vcn_v2_0_jpeg_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val)
|
||||
{
|
||||
uint32_t reg_offset = (reg << 2);
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
if (reg_offset >= 0x10000 && reg_offset <= 0x105ff) {
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring,
|
||||
PACKETJ((reg_offset >> 2), 0, 0, PACKETJ_TYPE0));
|
||||
} else {
|
||||
amdgpu_ring_write(ring, reg_offset);
|
||||
amdgpu_ring_write(ring, PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
}
|
||||
amdgpu_ring_write(ring, val);
|
||||
}
|
||||
|
||||
void vcn_v2_0_jpeg_ring_nop(struct amdgpu_ring *ring, uint32_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
WARN_ON(ring->wptr % 2 || count % 2);
|
||||
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
amdgpu_ring_write(ring, PACKETJ(0, 0, 0, PACKETJ_TYPE6));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int vcn_v2_0_set_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
@ -2071,9 +1620,6 @@ static int vcn_v2_0_process_interrupt(struct amdgpu_device *adev,
|
||||
case VCN_2_0__SRCID__UVD_ENC_LOW_LATENCY:
|
||||
amdgpu_fence_process(&adev->vcn.inst->ring_enc[1]);
|
||||
break;
|
||||
case VCN_2_0__SRCID__JPEG_DECODE:
|
||||
amdgpu_fence_process(&adev->vcn.inst->ring_jpeg);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
@ -2219,36 +1765,6 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static const struct amdgpu_ring_funcs vcn_v2_0_jpeg_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.vmhub = AMDGPU_MMHUB_0,
|
||||
.get_rptr = vcn_v2_0_jpeg_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_0_jpeg_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_0_jpeg_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* vcn_v2_0_jpeg_ring_emit_vm_flush */
|
||||
18 + 18 + /* vcn_v2_0_jpeg_ring_emit_fence x2 vm fence */
|
||||
8 + 16,
|
||||
.emit_ib_size = 22, /* vcn_v2_0_jpeg_ring_emit_ib */
|
||||
.emit_ib = vcn_v2_0_jpeg_ring_emit_ib,
|
||||
.emit_fence = vcn_v2_0_jpeg_ring_emit_fence,
|
||||
.emit_vm_flush = vcn_v2_0_jpeg_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_vcn_jpeg_ring_test_ring,
|
||||
.test_ib = amdgpu_vcn_jpeg_ring_test_ib,
|
||||
.insert_nop = vcn_v2_0_jpeg_ring_nop,
|
||||
.insert_start = vcn_v2_0_jpeg_ring_insert_start,
|
||||
.insert_end = vcn_v2_0_jpeg_ring_insert_end,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.begin_use = amdgpu_vcn_ring_begin_use,
|
||||
.end_use = amdgpu_vcn_ring_end_use,
|
||||
.emit_wreg = vcn_v2_0_jpeg_ring_emit_wreg,
|
||||
.emit_reg_wait = vcn_v2_0_jpeg_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_dec.funcs = &vcn_v2_0_dec_ring_vm_funcs;
|
||||
@ -2265,12 +1781,6 @@ static void vcn_v2_0_set_enc_ring_funcs(struct amdgpu_device *adev)
|
||||
DRM_INFO("VCN encode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static void vcn_v2_0_set_jpeg_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->ring_jpeg.funcs = &vcn_v2_0_jpeg_ring_vm_funcs;
|
||||
DRM_INFO("VCN jpeg decode is enabled in VM mode\n");
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
|
||||
.set = vcn_v2_0_set_interrupt_state,
|
||||
.process = vcn_v2_0_process_interrupt,
|
||||
@ -2278,7 +1788,7 @@ static const struct amdgpu_irq_src_funcs vcn_v2_0_irq_funcs = {
|
||||
|
||||
static void vcn_v2_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 2;
|
||||
adev->vcn.inst->irq.num_types = adev->vcn.num_enc_rings + 1;
|
||||
adev->vcn.inst->irq.funcs = &vcn_v2_0_irq_funcs;
|
||||
}
|
||||
|
||||
|
@ -49,19 +49,6 @@ extern void vcn_v2_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned int vmid, uint64_t pd_addr);
|
||||
extern void vcn_v2_0_enc_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
|
||||
|
||||
extern void vcn_v2_0_jpeg_ring_insert_start(struct amdgpu_ring *ring);
|
||||
extern void vcn_v2_0_jpeg_ring_insert_end(struct amdgpu_ring *ring);
|
||||
extern void vcn_v2_0_jpeg_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags);
|
||||
extern void vcn_v2_0_jpeg_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib, uint32_t flags);
|
||||
extern void vcn_v2_0_jpeg_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val, uint32_t mask);
|
||||
extern void vcn_v2_0_jpeg_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr);
|
||||
extern void vcn_v2_0_jpeg_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
|
||||
extern void vcn_v2_0_jpeg_ring_nop(struct amdgpu_ring *ring, uint32_t count);
|
||||
|
||||
extern const struct amdgpu_ip_block_version vcn_v2_0_ip_block;
|
||||
|
||||
#endif /* __VCN_V2_0_H__ */
|
||||
|
@ -47,13 +47,10 @@
|
||||
#define mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH_INTERNAL_OFFSET 0x3b5
|
||||
#define mmUVD_RBC_IB_SIZE_INTERNAL_OFFSET 0x25c
|
||||
|
||||
#define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f
|
||||
|
||||
#define VCN25_MAX_HW_INSTANCES_ARCTURUS 2
|
||||
#define VCN25_MAX_HW_INSTANCES_ARCTURUS 2
|
||||
|
||||
static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_5_set_jpeg_ring_funcs(struct amdgpu_device *adev);
|
||||
static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev);
|
||||
static int vcn_v2_5_set_powergating_state(void *handle,
|
||||
enum amd_powergating_state state);
|
||||
@ -95,7 +92,6 @@ static int vcn_v2_5_early_init(void *handle)
|
||||
|
||||
vcn_v2_5_set_dec_ring_funcs(adev);
|
||||
vcn_v2_5_set_enc_ring_funcs(adev);
|
||||
vcn_v2_5_set_jpeg_ring_funcs(adev);
|
||||
vcn_v2_5_set_irq_funcs(adev);
|
||||
|
||||
return 0;
|
||||
@ -130,12 +126,6 @@ static int vcn_v2_5_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* VCN JPEG TRAP */
|
||||
r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j],
|
||||
VCN_2_0__SRCID__JPEG_DECODE, &adev->vcn.inst[j].irq);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_vcn_sw_init(adev);
|
||||
@ -184,9 +174,6 @@ static int vcn_v2_5_sw_init(void *handle)
|
||||
adev->vcn.internal.nop = mmUVD_NO_OP_INTERNAL_OFFSET;
|
||||
adev->vcn.inst[j].external.nop = SOC15_REG_OFFSET(UVD, j, mmUVD_NO_OP);
|
||||
|
||||
adev->vcn.internal.jpeg_pitch = mmUVD_JPEG_PITCH_INTERNAL_OFFSET;
|
||||
adev->vcn.inst[j].external.jpeg_pitch = SOC15_REG_OFFSET(UVD, j, mmUVD_JPEG_PITCH);
|
||||
|
||||
ring = &adev->vcn.inst[j].ring_dec;
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8*j;
|
||||
@ -204,14 +191,6 @@ static int vcn_v2_5_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst[j].ring_jpeg;
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8*j;
|
||||
sprintf(ring->name, "vcn_jpeg_%d", j);
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[j].irq, 0);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -269,12 +248,8 @@ static int vcn_v2_5_hw_init(void *handle)
|
||||
if (r)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst[j].ring_jpeg;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!r)
|
||||
DRM_INFO("VCN decode and encode initialized successfully.\n");
|
||||
@ -309,9 +284,6 @@ static int vcn_v2_5_hw_fini(void *handle)
|
||||
ring = &adev->vcn.inst[i].ring_enc[j];
|
||||
ring->sched.ready = false;
|
||||
}
|
||||
|
||||
ring = &adev->vcn.inst[i].ring_jpeg;
|
||||
ring->sched.ready = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -592,115 +564,6 @@ static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_start - start JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup and start the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
ring = &adev->vcn.inst[i].ring_jpeg;
|
||||
/* disable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, i, mmUVD_JPEG_POWER_STATUS), 0,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
|
||||
/* JPEG disable CGC */
|
||||
tmp = RREG32_SOC15(VCN, i, mmJPEG_CGC_CTRL);
|
||||
tmp |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
|
||||
tmp |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
|
||||
tmp |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
|
||||
WREG32_SOC15(VCN, i, mmJPEG_CGC_CTRL, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(VCN, i, mmJPEG_CGC_GATE);
|
||||
tmp &= ~(JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
| JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
| JPEG_CGC_GATE__JMCIF_MASK
|
||||
| JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(VCN, i, mmJPEG_CGC_GATE, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(VCN, i, mmJPEG_CGC_CTRL);
|
||||
tmp &= ~(JPEG_CGC_CTRL__JPEG_DEC_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JPEG2_DEC_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JMCIF_MODE_MASK
|
||||
| JPEG_CGC_CTRL__JRBBM_MODE_MASK);
|
||||
WREG32_SOC15(VCN, i, mmJPEG_CGC_CTRL, tmp);
|
||||
|
||||
/* MJPEG global tiling registers */
|
||||
WREG32_SOC15(UVD, i, mmJPEG_DEC_GFX8_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
WREG32_SOC15(UVD, i, mmJPEG_DEC_GFX10_ADDR_CONFIG,
|
||||
adev->gfx.config.gb_addr_config);
|
||||
|
||||
/* enable JMI channel */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, i, mmUVD_JMI_CNTL), 0,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
/* enable System Interrupt for JRBC */
|
||||
WREG32_P(SOC15_REG_OFFSET(VCN, i, mmJPEG_SYS_INT_EN),
|
||||
JPEG_SYS_INT_EN__DJRBC_MASK,
|
||||
~JPEG_SYS_INT_EN__DJRBC_MASK);
|
||||
|
||||
WREG32_SOC15(UVD, i, mmUVD_LMI_JRBC_RB_VMID, 0);
|
||||
WREG32_SOC15(UVD, i, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
|
||||
WREG32_SOC15(UVD, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, i, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
|
||||
upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, i, mmUVD_JRBC_RB_RPTR, 0);
|
||||
WREG32_SOC15(UVD, i, mmUVD_JRBC_RB_WPTR, 0);
|
||||
WREG32_SOC15(UVD, i, mmUVD_JRBC_RB_CNTL, 0x00000002L);
|
||||
WREG32_SOC15(UVD, i, mmUVD_JRBC_RB_SIZE, ring->ring_size / 4);
|
||||
ring->wptr = RREG32_SOC15(UVD, i, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* jpeg_v2_5_stop - stop JPEG block
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* stop the JPEG block
|
||||
*/
|
||||
static int jpeg_v2_5_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
/* reset JMI */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, i, mmUVD_JMI_CNTL),
|
||||
UVD_JMI_CNTL__SOFT_RESET_MASK,
|
||||
~UVD_JMI_CNTL__SOFT_RESET_MASK);
|
||||
|
||||
tmp = RREG32_SOC15(VCN, i, mmJPEG_CGC_GATE);
|
||||
tmp |= (JPEG_CGC_GATE__JPEG_DEC_MASK
|
||||
|JPEG_CGC_GATE__JPEG2_DEC_MASK
|
||||
|JPEG_CGC_GATE__JMCIF_MASK
|
||||
|JPEG_CGC_GATE__JRBBM_MASK);
|
||||
WREG32_SOC15(VCN, i, mmJPEG_CGC_GATE, tmp);
|
||||
|
||||
/* enable anti hang mechanism */
|
||||
WREG32_P(SOC15_REG_OFFSET(UVD, i, mmUVD_JPEG_POWER_STATUS),
|
||||
UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK,
|
||||
~UVD_JPEG_POWER_STATUS__JPEG_POWER_STATUS_MASK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v2_5_start(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
@ -874,19 +737,14 @@ static int vcn_v2_5_start(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(UVD, i, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
|
||||
WREG32_SOC15(UVD, i, mmUVD_RB_SIZE2, ring->ring_size / 4);
|
||||
}
|
||||
r = jpeg_v2_5_start(adev);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v2_5_stop(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t tmp;
|
||||
int i, r;
|
||||
|
||||
r = jpeg_v2_5_stop(adev);
|
||||
if (r)
|
||||
return r;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
@ -1125,86 +983,6 @@ static const struct amdgpu_ring_funcs vcn_v2_5_enc_ring_vm_funcs = {
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
/**
|
||||
* vcn_v2_5_jpeg_ring_get_rptr - get read pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware read pointer
|
||||
*/
|
||||
static uint64_t vcn_v2_5_jpeg_ring_get_rptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
return RREG32_SOC15(UVD, ring->me, mmUVD_JRBC_RB_RPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_5_jpeg_ring_get_wptr - get write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Returns the current hardware write pointer
|
||||
*/
|
||||
static uint64_t vcn_v2_5_jpeg_ring_get_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell)
|
||||
return adev->wb.wb[ring->wptr_offs];
|
||||
else
|
||||
return RREG32_SOC15(UVD, ring->me, mmUVD_JRBC_RB_WPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* vcn_v2_5_jpeg_ring_set_wptr - set write pointer
|
||||
*
|
||||
* @ring: amdgpu_ring pointer
|
||||
*
|
||||
* Commits the write pointer to the hardware
|
||||
*/
|
||||
static void vcn_v2_5_jpeg_ring_set_wptr(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
if (ring->use_doorbell) {
|
||||
adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
|
||||
WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
|
||||
} else {
|
||||
WREG32_SOC15(UVD, ring->me, mmUVD_JRBC_RB_WPTR, lower_32_bits(ring->wptr));
|
||||
}
|
||||
}
|
||||
|
||||
static const struct amdgpu_ring_funcs vcn_v2_5_jpeg_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.vmhub = AMDGPU_MMHUB_1,
|
||||
.get_rptr = vcn_v2_5_jpeg_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_5_jpeg_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_5_jpeg_ring_set_wptr,
|
||||
.emit_frame_size =
|
||||
SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
|
||||
SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
|
||||
8 + /* vcn_v2_0_jpeg_ring_emit_vm_flush */
|
||||
18 + 18 + /* vcn_v2_0_jpeg_ring_emit_fence x2 vm fence */
|
||||
8 + 16,
|
||||
.emit_ib_size = 22, /* vcn_v2_0_jpeg_ring_emit_ib */
|
||||
.emit_ib = vcn_v2_0_jpeg_ring_emit_ib,
|
||||
.emit_fence = vcn_v2_0_jpeg_ring_emit_fence,
|
||||
.emit_vm_flush = vcn_v2_0_jpeg_ring_emit_vm_flush,
|
||||
.test_ring = amdgpu_vcn_jpeg_ring_test_ring,
|
||||
.test_ib = amdgpu_vcn_jpeg_ring_test_ib,
|
||||
.insert_nop = vcn_v2_0_jpeg_ring_nop,
|
||||
.insert_start = vcn_v2_0_jpeg_ring_insert_start,
|
||||
.insert_end = vcn_v2_0_jpeg_ring_insert_end,
|
||||
.pad_ib = amdgpu_ring_generic_pad_ib,
|
||||
.begin_use = amdgpu_vcn_ring_begin_use,
|
||||
.end_use = amdgpu_vcn_ring_end_use,
|
||||
.emit_wreg = vcn_v2_0_jpeg_ring_emit_wreg,
|
||||
.emit_reg_wait = vcn_v2_0_jpeg_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
|
||||
};
|
||||
|
||||
static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
@ -1233,19 +1011,6 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
static void vcn_v2_5_set_jpeg_ring_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
adev->vcn.inst[i].ring_jpeg.funcs = &vcn_v2_5_jpeg_ring_vm_funcs;
|
||||
adev->vcn.inst[i].ring_jpeg.me = i;
|
||||
DRM_INFO("VCN(%d) jpeg decode is enabled in VM mode\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
static bool vcn_v2_5_is_idle(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
@ -1352,9 +1117,6 @@ static int vcn_v2_5_process_interrupt(struct amdgpu_device *adev,
|
||||
case VCN_2_0__SRCID__UVD_ENC_LOW_LATENCY:
|
||||
amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[1]);
|
||||
break;
|
||||
case VCN_2_0__SRCID__JPEG_DECODE:
|
||||
amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_jpeg);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unhandled interrupt: %d %d\n",
|
||||
entry->src_id, entry->src_data[0]);
|
||||
@ -1376,7 +1138,7 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev)
|
||||
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
||||
if (adev->vcn.harvest_config & (1 << i))
|
||||
continue;
|
||||
adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 2;
|
||||
adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
|
||||
adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs;
|
||||
}
|
||||
}
|
||||
|
@ -745,6 +745,27 @@ static int vi_asic_pci_config_reset(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool vi_asic_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
bool baco_support;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_FIJI:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_TOPAZ:
|
||||
smu7_asic_get_baco_capability(adev, &baco_support);
|
||||
break;
|
||||
default:
|
||||
baco_support = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return baco_support;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
vi_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -1119,6 +1140,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
|
||||
.get_pcie_usage = &vi_get_pcie_usage,
|
||||
.need_reset_on_init = &vi_need_reset_on_init,
|
||||
.get_pcie_replay_count = &vi_get_pcie_replay_count,
|
||||
.supports_baco = &vi_asic_supports_baco,
|
||||
};
|
||||
|
||||
#define CZ_REV_BRISTOL(rev) \
|
||||
|
@ -38,11 +38,9 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \
|
||||
$(AMDKFD_PATH)/kfd_mqd_manager_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_mqd_manager_v10.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_cik.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_vi.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_kernel_queue_v10.o \
|
||||
$(AMDKFD_PATH)/kfd_packet_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_packet_manager_vi.o \
|
||||
$(AMDKFD_PATH)/kfd_packet_manager_v9.o \
|
||||
$(AMDKFD_PATH)/kfd_process_queue_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager.o \
|
||||
$(AMDKFD_PATH)/kfd_device_queue_manager_cik.o \
|
||||
|
@ -258,6 +258,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
|
||||
unsigned int queue_id;
|
||||
struct kfd_process_device *pdd;
|
||||
struct queue_properties q_properties;
|
||||
uint32_t doorbell_offset_in_process = 0;
|
||||
|
||||
memset(&q_properties, 0, sizeof(struct queue_properties));
|
||||
|
||||
@ -286,7 +287,8 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
|
||||
p->pasid,
|
||||
dev->id);
|
||||
|
||||
err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id);
|
||||
err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id,
|
||||
&doorbell_offset_in_process);
|
||||
if (err != 0)
|
||||
goto err_create_queue;
|
||||
|
||||
@ -296,14 +298,11 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
|
||||
/* Return gpu_id as doorbell offset for mmap usage */
|
||||
args->doorbell_offset = KFD_MMAP_TYPE_DOORBELL;
|
||||
args->doorbell_offset |= KFD_MMAP_GPU_ID(args->gpu_id);
|
||||
args->doorbell_offset <<= PAGE_SHIFT;
|
||||
if (KFD_IS_SOC15(dev->device_info->asic_family))
|
||||
/* On SOC15 ASICs, doorbell allocation must be
|
||||
* per-device, and independent from the per-process
|
||||
* queue_id. Return the doorbell offset within the
|
||||
* doorbell aperture to user mode.
|
||||
/* On SOC15 ASICs, include the doorbell offset within the
|
||||
* process doorbell frame, which is 2 pages.
|
||||
*/
|
||||
args->doorbell_offset |= q_properties.doorbell_off;
|
||||
args->doorbell_offset |= doorbell_offset_in_process;
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
@ -1312,10 +1311,9 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
|
||||
/* MMIO is mapped through kfd device
|
||||
* Generate a kfd mmap offset
|
||||
*/
|
||||
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) {
|
||||
args->mmap_offset = KFD_MMAP_TYPE_MMIO | KFD_MMAP_GPU_ID(args->gpu_id);
|
||||
args->mmap_offset <<= PAGE_SHIFT;
|
||||
}
|
||||
if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)
|
||||
args->mmap_offset = KFD_MMAP_TYPE_MMIO
|
||||
| KFD_MMAP_GPU_ID(args->gpu_id);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1899,20 +1897,19 @@ static int kfd_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct kfd_process *process;
|
||||
struct kfd_dev *dev = NULL;
|
||||
unsigned long vm_pgoff;
|
||||
unsigned long mmap_offset;
|
||||
unsigned int gpu_id;
|
||||
|
||||
process = kfd_get_process(current);
|
||||
if (IS_ERR(process))
|
||||
return PTR_ERR(process);
|
||||
|
||||
vm_pgoff = vma->vm_pgoff;
|
||||
vma->vm_pgoff = KFD_MMAP_OFFSET_VALUE_GET(vm_pgoff);
|
||||
gpu_id = KFD_MMAP_GPU_ID_GET(vm_pgoff);
|
||||
mmap_offset = vma->vm_pgoff << PAGE_SHIFT;
|
||||
gpu_id = KFD_MMAP_GET_GPU_ID(mmap_offset);
|
||||
if (gpu_id)
|
||||
dev = kfd_device_by_id(gpu_id);
|
||||
|
||||
switch (vm_pgoff & KFD_MMAP_TYPE_MASK) {
|
||||
switch (mmap_offset & KFD_MMAP_TYPE_MASK) {
|
||||
case KFD_MMAP_TYPE_DOORBELL:
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
@ -72,11 +72,11 @@ static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev,
|
||||
* The receive packet buff will be sitting on the Indirect Buffer
|
||||
* and in the PQ we put the IB packet + sync packet(s).
|
||||
*/
|
||||
status = kq->ops.acquire_packet_buffer(kq,
|
||||
status = kq_acquire_packet_buffer(kq,
|
||||
pq_packets_size_in_bytes / sizeof(uint32_t),
|
||||
&ib_packet_buff);
|
||||
if (status) {
|
||||
pr_err("acquire_packet_buffer failed\n");
|
||||
pr_err("kq_acquire_packet_buffer failed\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev,
|
||||
|
||||
if (status) {
|
||||
pr_err("Failed to allocate GART memory\n");
|
||||
kq->ops.rollback_packet(kq);
|
||||
kq_rollback_packet(kq);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev,
|
||||
|
||||
rm_packet->data_lo = QUEUESTATE__ACTIVE;
|
||||
|
||||
kq->ops.submit_packet(kq);
|
||||
kq_submit_packet(kq);
|
||||
|
||||
/* Wait till CP writes sync code: */
|
||||
status = amdkfd_fence_wait_timeout(
|
||||
@ -185,7 +185,7 @@ static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev)
|
||||
properties.type = KFD_QUEUE_TYPE_DIQ;
|
||||
|
||||
status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL,
|
||||
&properties, &qid);
|
||||
&properties, &qid, NULL);
|
||||
|
||||
if (status) {
|
||||
pr_err("Failed to create DIQ\n");
|
||||
|
@ -742,7 +742,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd)
|
||||
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
int ret, count;
|
||||
int ret;
|
||||
|
||||
if (!kfd->init_complete)
|
||||
return 0;
|
||||
@ -750,7 +750,7 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd)
|
||||
ret = kfd_resume(kfd);
|
||||
if (ret)
|
||||
return ret;
|
||||
count = atomic_dec_return(&kfd_locked);
|
||||
atomic_dec(&kfd_locked);
|
||||
|
||||
atomic_set(&kfd->sram_ecc_flag, 0);
|
||||
|
||||
|
@ -170,7 +170,7 @@ static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q)
|
||||
}
|
||||
|
||||
q->properties.doorbell_off =
|
||||
kfd_doorbell_id_to_offset(dev, q->process,
|
||||
kfd_get_doorbell_dw_offset_in_bar(dev, q->process,
|
||||
q->doorbell_id);
|
||||
|
||||
return 0;
|
||||
@ -1595,7 +1595,7 @@ static int get_wave_state(struct device_queue_manager *dqm,
|
||||
goto dqm_unlock;
|
||||
}
|
||||
|
||||
mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_COMPUTE];
|
||||
mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP];
|
||||
|
||||
if (!mqd_mgr->get_wave_state) {
|
||||
r = -EINVAL;
|
||||
|
@ -91,7 +91,7 @@ int kfd_doorbell_init(struct kfd_dev *kfd)
|
||||
kfd->doorbell_base = kfd->shared_resources.doorbell_physical_address +
|
||||
doorbell_start_offset;
|
||||
|
||||
kfd->doorbell_id_offset = doorbell_start_offset / sizeof(u32);
|
||||
kfd->doorbell_base_dw_offset = doorbell_start_offset / sizeof(u32);
|
||||
|
||||
kfd->doorbell_kernel_ptr = ioremap(kfd->doorbell_base,
|
||||
kfd_doorbell_process_slice(kfd));
|
||||
@ -103,8 +103,8 @@ int kfd_doorbell_init(struct kfd_dev *kfd)
|
||||
pr_debug("doorbell base == 0x%08lX\n",
|
||||
(uintptr_t)kfd->doorbell_base);
|
||||
|
||||
pr_debug("doorbell_id_offset == 0x%08lX\n",
|
||||
kfd->doorbell_id_offset);
|
||||
pr_debug("doorbell_base_dw_offset == 0x%08lX\n",
|
||||
kfd->doorbell_base_dw_offset);
|
||||
|
||||
pr_debug("doorbell_process_limit == 0x%08lX\n",
|
||||
doorbell_process_limit);
|
||||
@ -185,7 +185,7 @@ void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
|
||||
* Calculating the kernel doorbell offset using the first
|
||||
* doorbell page.
|
||||
*/
|
||||
*doorbell_off = kfd->doorbell_id_offset + inx;
|
||||
*doorbell_off = kfd->doorbell_base_dw_offset + inx;
|
||||
|
||||
pr_debug("Get kernel queue doorbell\n"
|
||||
" doorbell offset == 0x%08X\n"
|
||||
@ -225,17 +225,17 @@ void write_kernel_doorbell64(void __iomem *db, u64 value)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd,
|
||||
unsigned int kfd_get_doorbell_dw_offset_in_bar(struct kfd_dev *kfd,
|
||||
struct kfd_process *process,
|
||||
unsigned int doorbell_id)
|
||||
{
|
||||
/*
|
||||
* doorbell_id_offset accounts for doorbells taken by KGD.
|
||||
* doorbell_base_dw_offset accounts for doorbells taken by KGD.
|
||||
* index * kfd_doorbell_process_slice/sizeof(u32) adjusts to
|
||||
* the process's doorbells. The offset returned is in dword
|
||||
* units regardless of the ASIC-dependent doorbell size.
|
||||
*/
|
||||
return kfd->doorbell_id_offset +
|
||||
return kfd->doorbell_base_dw_offset +
|
||||
process->doorbell_index
|
||||
* kfd_doorbell_process_slice(kfd) / sizeof(u32) +
|
||||
doorbell_id * kfd->device_info->doorbell_size / sizeof(u32);
|
||||
|
@ -346,7 +346,6 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p,
|
||||
ret = create_signal_event(devkfd, p, ev);
|
||||
if (!ret) {
|
||||
*event_page_offset = KFD_MMAP_TYPE_EVENTS;
|
||||
*event_page_offset <<= PAGE_SHIFT;
|
||||
*event_slot_index = ev->event_id;
|
||||
}
|
||||
break;
|
||||
|
@ -62,9 +62,6 @@ int kfd_iommu_device_init(struct kfd_dev *kfd)
|
||||
struct amd_iommu_device_info iommu_info;
|
||||
unsigned int pasid_limit;
|
||||
int err;
|
||||
struct kfd_topology_device *top_dev;
|
||||
|
||||
top_dev = kfd_topology_device_by_id(kfd->id);
|
||||
|
||||
if (!kfd->device_info->needs_iommu_device)
|
||||
return 0;
|
||||
|
@ -34,7 +34,10 @@
|
||||
|
||||
#define PM4_COUNT_ZERO (((1 << 15) - 1) << 16)
|
||||
|
||||
static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
/* Initialize a kernel queue, including allocations of GART memory
|
||||
* needed for the queue.
|
||||
*/
|
||||
static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size)
|
||||
{
|
||||
struct queue_properties prop;
|
||||
@ -87,9 +90,17 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
kq->pq_kernel_addr = kq->pq->cpu_ptr;
|
||||
kq->pq_gpu_addr = kq->pq->gpu_addr;
|
||||
|
||||
retval = kq->ops_asic_specific.initialize(kq, dev, type, queue_size);
|
||||
if (!retval)
|
||||
goto err_eop_allocate_vidmem;
|
||||
/* For CIK family asics, kq->eop_mem is not needed */
|
||||
if (dev->device_info->asic_family > CHIP_MULLINS) {
|
||||
retval = kfd_gtt_sa_allocate(dev, PAGE_SIZE, &kq->eop_mem);
|
||||
if (retval != 0)
|
||||
goto err_eop_allocate_vidmem;
|
||||
|
||||
kq->eop_gpu_addr = kq->eop_mem->gpu_addr;
|
||||
kq->eop_kernel_addr = kq->eop_mem->cpu_ptr;
|
||||
|
||||
memset(kq->eop_kernel_addr, 0, PAGE_SIZE);
|
||||
}
|
||||
|
||||
retval = kfd_gtt_sa_allocate(dev, sizeof(*kq->rptr_kernel),
|
||||
&kq->rptr_mem);
|
||||
@ -183,7 +194,8 @@ err_get_kernel_doorbell:
|
||||
|
||||
}
|
||||
|
||||
static void uninitialize(struct kernel_queue *kq)
|
||||
/* Uninitialize a kernel queue and free all its memory usages. */
|
||||
static void kq_uninitialize(struct kernel_queue *kq)
|
||||
{
|
||||
if (kq->queue->properties.type == KFD_QUEUE_TYPE_HIQ)
|
||||
kq->mqd_mgr->destroy_mqd(kq->mqd_mgr,
|
||||
@ -200,14 +212,19 @@ static void uninitialize(struct kernel_queue *kq)
|
||||
|
||||
kfd_gtt_sa_free(kq->dev, kq->rptr_mem);
|
||||
kfd_gtt_sa_free(kq->dev, kq->wptr_mem);
|
||||
kq->ops_asic_specific.uninitialize(kq);
|
||||
|
||||
/* For CIK family asics, kq->eop_mem is Null, kfd_gtt_sa_free()
|
||||
* is able to handle NULL properly.
|
||||
*/
|
||||
kfd_gtt_sa_free(kq->dev, kq->eop_mem);
|
||||
|
||||
kfd_gtt_sa_free(kq->dev, kq->pq);
|
||||
kfd_release_kernel_doorbell(kq->dev,
|
||||
kq->queue->properties.doorbell_ptr);
|
||||
uninit_queue(kq->queue);
|
||||
}
|
||||
|
||||
static int acquire_packet_buffer(struct kernel_queue *kq,
|
||||
int kq_acquire_packet_buffer(struct kernel_queue *kq,
|
||||
size_t packet_size_in_dwords, unsigned int **buffer_ptr)
|
||||
{
|
||||
size_t available_size;
|
||||
@ -268,7 +285,7 @@ err_no_space:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void submit_packet(struct kernel_queue *kq)
|
||||
void kq_submit_packet(struct kernel_queue *kq)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
@ -280,11 +297,18 @@ static void submit_packet(struct kernel_queue *kq)
|
||||
}
|
||||
pr_debug("\n");
|
||||
#endif
|
||||
|
||||
kq->ops_asic_specific.submit_packet(kq);
|
||||
if (kq->dev->device_info->doorbell_size == 8) {
|
||||
*kq->wptr64_kernel = kq->pending_wptr64;
|
||||
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
|
||||
kq->pending_wptr64);
|
||||
} else {
|
||||
*kq->wptr_kernel = kq->pending_wptr;
|
||||
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
|
||||
kq->pending_wptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void rollback_packet(struct kernel_queue *kq)
|
||||
void kq_rollback_packet(struct kernel_queue *kq)
|
||||
{
|
||||
if (kq->dev->device_info->doorbell_size == 8) {
|
||||
kq->pending_wptr64 = *kq->wptr64_kernel;
|
||||
@ -304,60 +328,18 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev,
|
||||
if (!kq)
|
||||
return NULL;
|
||||
|
||||
kq->ops.initialize = initialize;
|
||||
kq->ops.uninitialize = uninitialize;
|
||||
kq->ops.acquire_packet_buffer = acquire_packet_buffer;
|
||||
kq->ops.submit_packet = submit_packet;
|
||||
kq->ops.rollback_packet = rollback_packet;
|
||||
|
||||
switch (dev->device_info->asic_family) {
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS12:
|
||||
case CHIP_VEGAM:
|
||||
kernel_queue_init_vi(&kq->ops_asic_specific);
|
||||
break;
|
||||
|
||||
case CHIP_KAVERI:
|
||||
case CHIP_HAWAII:
|
||||
kernel_queue_init_cik(&kq->ops_asic_specific);
|
||||
break;
|
||||
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA12:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_RAVEN:
|
||||
case CHIP_RENOIR:
|
||||
case CHIP_ARCTURUS:
|
||||
kernel_queue_init_v9(&kq->ops_asic_specific);
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_NAVI14:
|
||||
kernel_queue_init_v10(&kq->ops_asic_specific);
|
||||
break;
|
||||
default:
|
||||
WARN(1, "Unexpected ASIC family %u",
|
||||
dev->device_info->asic_family);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE))
|
||||
if (kq_initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE))
|
||||
return kq;
|
||||
|
||||
pr_err("Failed to init kernel queue\n");
|
||||
|
||||
out_free:
|
||||
kfree(kq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kernel_queue_uninit(struct kernel_queue *kq)
|
||||
{
|
||||
kq->ops.uninitialize(kq);
|
||||
kq_uninitialize(kq);
|
||||
kfree(kq);
|
||||
}
|
||||
|
||||
@ -377,7 +359,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
retval = kq->ops.acquire_packet_buffer(kq, 5, &buffer);
|
||||
retval = kq_acquire_packet_buffer(kq, 5, &buffer);
|
||||
if (unlikely(retval != 0)) {
|
||||
pr_err(" Failed to acquire packet buffer\n");
|
||||
pr_err("Kernel queue test failed\n");
|
||||
@ -385,7 +367,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev)
|
||||
}
|
||||
for (i = 0; i < 5; i++)
|
||||
buffer[i] = kq->nop_packet;
|
||||
kq->ops.submit_packet(kq);
|
||||
kq_submit_packet(kq);
|
||||
|
||||
pr_err("Ending kernel queue test\n");
|
||||
}
|
||||
|
@ -29,45 +29,28 @@
|
||||
#include "kfd_priv.h"
|
||||
|
||||
/**
|
||||
* struct kernel_queue_ops
|
||||
*
|
||||
* @initialize: Initialize a kernel queue, including allocations of GART memory
|
||||
* needed for the queue.
|
||||
*
|
||||
* @uninitialize: Uninitialize a kernel queue and free all its memory usages.
|
||||
*
|
||||
* @acquire_packet_buffer: Returns a pointer to the location in the kernel
|
||||
* kq_acquire_packet_buffer: Returns a pointer to the location in the kernel
|
||||
* queue ring buffer where the calling function can write its packet. It is
|
||||
* Guaranteed that there is enough space for that packet. It also updates the
|
||||
* pending write pointer to that location so subsequent calls to
|
||||
* acquire_packet_buffer will get a correct write pointer
|
||||
*
|
||||
* @submit_packet: Update the write pointer and doorbell of a kernel queue.
|
||||
* kq_submit_packet: Update the write pointer and doorbell of a kernel queue.
|
||||
*
|
||||
* @sync_with_hw: Wait until the write pointer and the read pointer of a kernel
|
||||
* queue are equal, which means the CP has read all the submitted packets.
|
||||
*
|
||||
* @rollback_packet: This routine is called if we failed to build an acquired
|
||||
* kq_rollback_packet: This routine is called if we failed to build an acquired
|
||||
* packet for some reason. It just overwrites the pending wptr with the current
|
||||
* one
|
||||
*
|
||||
*/
|
||||
struct kernel_queue_ops {
|
||||
bool (*initialize)(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size);
|
||||
void (*uninitialize)(struct kernel_queue *kq);
|
||||
int (*acquire_packet_buffer)(struct kernel_queue *kq,
|
||||
size_t packet_size_in_dwords,
|
||||
unsigned int **buffer_ptr);
|
||||
|
||||
void (*submit_packet)(struct kernel_queue *kq);
|
||||
void (*rollback_packet)(struct kernel_queue *kq);
|
||||
};
|
||||
int kq_acquire_packet_buffer(struct kernel_queue *kq,
|
||||
size_t packet_size_in_dwords,
|
||||
unsigned int **buffer_ptr);
|
||||
void kq_submit_packet(struct kernel_queue *kq);
|
||||
void kq_rollback_packet(struct kernel_queue *kq);
|
||||
|
||||
|
||||
struct kernel_queue {
|
||||
struct kernel_queue_ops ops;
|
||||
struct kernel_queue_ops ops_asic_specific;
|
||||
|
||||
/* data */
|
||||
struct kfd_dev *dev;
|
||||
struct mqd_manager *mqd_mgr;
|
||||
@ -99,9 +82,4 @@ struct kernel_queue {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void kernel_queue_init_cik(struct kernel_queue_ops *ops);
|
||||
void kernel_queue_init_vi(struct kernel_queue_ops *ops);
|
||||
void kernel_queue_init_v9(struct kernel_queue_ops *ops);
|
||||
void kernel_queue_init_v10(struct kernel_queue_ops *ops);
|
||||
|
||||
#endif /* KFD_KERNEL_QUEUE_H_ */
|
||||
|
@ -1,348 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kfd_kernel_queue.h"
|
||||
#include "kfd_device_queue_manager.h"
|
||||
#include "kfd_pm4_headers_ai.h"
|
||||
#include "kfd_pm4_opcodes.h"
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
|
||||
static bool initialize_v10(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size);
|
||||
static void uninitialize_v10(struct kernel_queue *kq);
|
||||
static void submit_packet_v10(struct kernel_queue *kq);
|
||||
|
||||
void kernel_queue_init_v10(struct kernel_queue_ops *ops)
|
||||
{
|
||||
ops->initialize = initialize_v10;
|
||||
ops->uninitialize = uninitialize_v10;
|
||||
ops->submit_packet = submit_packet_v10;
|
||||
}
|
||||
|
||||
static bool initialize_v10(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = kfd_gtt_sa_allocate(dev, PAGE_SIZE, &kq->eop_mem);
|
||||
if (retval != 0)
|
||||
return false;
|
||||
|
||||
kq->eop_gpu_addr = kq->eop_mem->gpu_addr;
|
||||
kq->eop_kernel_addr = kq->eop_mem->cpu_ptr;
|
||||
|
||||
memset(kq->eop_kernel_addr, 0, PAGE_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void uninitialize_v10(struct kernel_queue *kq)
|
||||
{
|
||||
kfd_gtt_sa_free(kq->dev, kq->eop_mem);
|
||||
}
|
||||
|
||||
static void submit_packet_v10(struct kernel_queue *kq)
|
||||
{
|
||||
*kq->wptr64_kernel = kq->pending_wptr64;
|
||||
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
|
||||
kq->pending_wptr64);
|
||||
}
|
||||
|
||||
static int pm_map_process_v10(struct packet_manager *pm,
|
||||
uint32_t *buffer, struct qcm_process_device *qpd)
|
||||
{
|
||||
struct pm4_mes_map_process *packet;
|
||||
uint64_t vm_page_table_base_addr = qpd->page_table_base;
|
||||
|
||||
packet = (struct pm4_mes_map_process *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mes_map_process));
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_MAP_PROCESS,
|
||||
sizeof(struct pm4_mes_map_process));
|
||||
packet->bitfields2.diq_enable = (qpd->is_debug) ? 1 : 0;
|
||||
packet->bitfields2.process_quantum = 1;
|
||||
packet->bitfields2.pasid = qpd->pqm->process->pasid;
|
||||
packet->bitfields14.gds_size = qpd->gds_size;
|
||||
packet->bitfields14.num_gws = qpd->num_gws;
|
||||
packet->bitfields14.num_oac = qpd->num_oac;
|
||||
packet->bitfields14.sdma_enable = 1;
|
||||
|
||||
packet->bitfields14.num_queues = (qpd->is_debug) ? 0 : qpd->queue_count;
|
||||
|
||||
packet->sh_mem_config = qpd->sh_mem_config;
|
||||
packet->sh_mem_bases = qpd->sh_mem_bases;
|
||||
if (qpd->tba_addr) {
|
||||
packet->sq_shader_tba_lo = lower_32_bits(qpd->tba_addr >> 8);
|
||||
packet->sq_shader_tba_hi = (1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT) |
|
||||
upper_32_bits(qpd->tba_addr >> 8);
|
||||
packet->sq_shader_tma_lo = lower_32_bits(qpd->tma_addr >> 8);
|
||||
packet->sq_shader_tma_hi = upper_32_bits(qpd->tma_addr >> 8);
|
||||
}
|
||||
|
||||
packet->gds_addr_lo = lower_32_bits(qpd->gds_context_area);
|
||||
packet->gds_addr_hi = upper_32_bits(qpd->gds_context_area);
|
||||
|
||||
packet->vm_context_page_table_base_addr_lo32 =
|
||||
lower_32_bits(vm_page_table_base_addr);
|
||||
packet->vm_context_page_table_base_addr_hi32 =
|
||||
upper_32_bits(vm_page_table_base_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm_runlist_v10(struct packet_manager *pm, uint32_t *buffer,
|
||||
uint64_t ib, size_t ib_size_in_dwords, bool chain)
|
||||
{
|
||||
struct pm4_mes_runlist *packet;
|
||||
|
||||
int concurrent_proc_cnt = 0;
|
||||
struct kfd_dev *kfd = pm->dqm->dev;
|
||||
|
||||
/* Determine the number of processes to map together to HW:
|
||||
* it can not exceed the number of VMIDs available to the
|
||||
* scheduler, and it is determined by the smaller of the number
|
||||
* of processes in the runlist and kfd module parameter
|
||||
* hws_max_conc_proc.
|
||||
* Note: the arbitration between the number of VMIDs and
|
||||
* hws_max_conc_proc has been done in
|
||||
* kgd2kfd_device_init().
|
||||
*/
|
||||
concurrent_proc_cnt = min(pm->dqm->processes_count,
|
||||
kfd->max_proc_per_quantum);
|
||||
|
||||
|
||||
packet = (struct pm4_mes_runlist *)buffer;
|
||||
|
||||
memset(buffer, 0, sizeof(struct pm4_mes_runlist));
|
||||
packet->header.u32All = pm_build_pm4_header(IT_RUN_LIST,
|
||||
sizeof(struct pm4_mes_runlist));
|
||||
|
||||
packet->bitfields4.ib_size = ib_size_in_dwords;
|
||||
packet->bitfields4.chain = chain ? 1 : 0;
|
||||
packet->bitfields4.offload_polling = 0;
|
||||
packet->bitfields4.valid = 1;
|
||||
packet->bitfields4.process_cnt = concurrent_proc_cnt;
|
||||
packet->ordinal2 = lower_32_bits(ib);
|
||||
packet->ib_base_hi = upper_32_bits(ib);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm_map_queues_v10(struct packet_manager *pm, uint32_t *buffer,
|
||||
struct queue *q, bool is_static)
|
||||
{
|
||||
struct pm4_mes_map_queues *packet;
|
||||
bool use_static = is_static;
|
||||
|
||||
packet = (struct pm4_mes_map_queues *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mes_map_queues));
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_MAP_QUEUES,
|
||||
sizeof(struct pm4_mes_map_queues));
|
||||
packet->bitfields2.num_queues = 1;
|
||||
packet->bitfields2.queue_sel =
|
||||
queue_sel__mes_map_queues__map_to_hws_determined_queue_slots_vi;
|
||||
|
||||
packet->bitfields2.engine_sel =
|
||||
engine_sel__mes_map_queues__compute_vi;
|
||||
packet->bitfields2.queue_type =
|
||||
queue_type__mes_map_queues__normal_compute_vi;
|
||||
|
||||
switch (q->properties.type) {
|
||||
case KFD_QUEUE_TYPE_COMPUTE:
|
||||
if (use_static)
|
||||
packet->bitfields2.queue_type =
|
||||
queue_type__mes_map_queues__normal_latency_static_queue_vi;
|
||||
break;
|
||||
case KFD_QUEUE_TYPE_DIQ:
|
||||
packet->bitfields2.queue_type =
|
||||
queue_type__mes_map_queues__debug_interface_queue_vi;
|
||||
break;
|
||||
case KFD_QUEUE_TYPE_SDMA:
|
||||
case KFD_QUEUE_TYPE_SDMA_XGMI:
|
||||
packet->bitfields2.engine_sel = q->properties.sdma_engine_id +
|
||||
engine_sel__mes_map_queues__sdma0_vi;
|
||||
use_static = false; /* no static queues under SDMA */
|
||||
break;
|
||||
default:
|
||||
WARN(1, "queue type %d\n", q->properties.type);
|
||||
return -EINVAL;
|
||||
}
|
||||
packet->bitfields3.doorbell_offset =
|
||||
q->properties.doorbell_off;
|
||||
|
||||
packet->mqd_addr_lo =
|
||||
lower_32_bits(q->gart_mqd_addr);
|
||||
|
||||
packet->mqd_addr_hi =
|
||||
upper_32_bits(q->gart_mqd_addr);
|
||||
|
||||
packet->wptr_addr_lo =
|
||||
lower_32_bits((uint64_t)q->properties.write_ptr);
|
||||
|
||||
packet->wptr_addr_hi =
|
||||
upper_32_bits((uint64_t)q->properties.write_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm_unmap_queues_v10(struct packet_manager *pm, uint32_t *buffer,
|
||||
enum kfd_queue_type type,
|
||||
enum kfd_unmap_queues_filter filter,
|
||||
uint32_t filter_param, bool reset,
|
||||
unsigned int sdma_engine)
|
||||
{
|
||||
struct pm4_mes_unmap_queues *packet;
|
||||
|
||||
packet = (struct pm4_mes_unmap_queues *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mes_unmap_queues));
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_UNMAP_QUEUES,
|
||||
sizeof(struct pm4_mes_unmap_queues));
|
||||
switch (type) {
|
||||
case KFD_QUEUE_TYPE_COMPUTE:
|
||||
case KFD_QUEUE_TYPE_DIQ:
|
||||
packet->bitfields2.engine_sel =
|
||||
engine_sel__mes_unmap_queues__compute;
|
||||
break;
|
||||
case KFD_QUEUE_TYPE_SDMA:
|
||||
case KFD_QUEUE_TYPE_SDMA_XGMI:
|
||||
packet->bitfields2.engine_sel =
|
||||
engine_sel__mes_unmap_queues__sdma0 + sdma_engine;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "queue type %d\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reset)
|
||||
packet->bitfields2.action =
|
||||
action__mes_unmap_queues__reset_queues;
|
||||
else
|
||||
packet->bitfields2.action =
|
||||
action__mes_unmap_queues__preempt_queues;
|
||||
|
||||
switch (filter) {
|
||||
case KFD_UNMAP_QUEUES_FILTER_SINGLE_QUEUE:
|
||||
packet->bitfields2.queue_sel =
|
||||
queue_sel__mes_unmap_queues__perform_request_on_specified_queues;
|
||||
packet->bitfields2.num_queues = 1;
|
||||
packet->bitfields3b.doorbell_offset0 = filter_param;
|
||||
break;
|
||||
case KFD_UNMAP_QUEUES_FILTER_BY_PASID:
|
||||
packet->bitfields2.queue_sel =
|
||||
queue_sel__mes_unmap_queues__perform_request_on_pasid_queues;
|
||||
packet->bitfields3a.pasid = filter_param;
|
||||
break;
|
||||
case KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES:
|
||||
packet->bitfields2.queue_sel =
|
||||
queue_sel__mes_unmap_queues__unmap_all_queues;
|
||||
break;
|
||||
case KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES:
|
||||
/* in this case, we do not preempt static queues */
|
||||
packet->bitfields2.queue_sel =
|
||||
queue_sel__mes_unmap_queues__unmap_all_non_static_queues;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "filter %d\n", filter);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int pm_query_status_v10(struct packet_manager *pm, uint32_t *buffer,
|
||||
uint64_t fence_address, uint32_t fence_value)
|
||||
{
|
||||
struct pm4_mes_query_status *packet;
|
||||
|
||||
packet = (struct pm4_mes_query_status *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mes_query_status));
|
||||
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_QUERY_STATUS,
|
||||
sizeof(struct pm4_mes_query_status));
|
||||
|
||||
packet->bitfields2.context_id = 0;
|
||||
packet->bitfields2.interrupt_sel =
|
||||
interrupt_sel__mes_query_status__completion_status;
|
||||
packet->bitfields2.command =
|
||||
command__mes_query_status__fence_only_after_write_ack;
|
||||
|
||||
packet->addr_hi = upper_32_bits((uint64_t)fence_address);
|
||||
packet->addr_lo = lower_32_bits((uint64_t)fence_address);
|
||||
packet->data_hi = upper_32_bits((uint64_t)fence_value);
|
||||
packet->data_lo = lower_32_bits((uint64_t)fence_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pm_release_mem_v10(uint64_t gpu_addr, uint32_t *buffer)
|
||||
{
|
||||
struct pm4_mec_release_mem *packet;
|
||||
|
||||
WARN_ON(!buffer);
|
||||
|
||||
packet = (struct pm4_mec_release_mem *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mec_release_mem));
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_RELEASE_MEM,
|
||||
sizeof(struct pm4_mec_release_mem));
|
||||
|
||||
packet->bitfields2.event_type = CACHE_FLUSH_AND_INV_TS_EVENT;
|
||||
packet->bitfields2.event_index = event_index__mec_release_mem__end_of_pipe;
|
||||
packet->bitfields2.tcl1_action_ena = 1;
|
||||
packet->bitfields2.tc_action_ena = 1;
|
||||
packet->bitfields2.cache_policy = cache_policy__mec_release_mem__lru;
|
||||
|
||||
packet->bitfields3.data_sel = data_sel__mec_release_mem__send_32_bit_low;
|
||||
packet->bitfields3.int_sel =
|
||||
int_sel__mec_release_mem__send_interrupt_after_write_confirm;
|
||||
|
||||
packet->bitfields4.address_lo_32b = (gpu_addr & 0xffffffff) >> 2;
|
||||
packet->address_hi = upper_32_bits(gpu_addr);
|
||||
|
||||
packet->data_lo = 0;
|
||||
|
||||
return sizeof(struct pm4_mec_release_mem) / sizeof(unsigned int);
|
||||
}
|
||||
|
||||
const struct packet_manager_funcs kfd_v10_pm_funcs = {
|
||||
.map_process = pm_map_process_v10,
|
||||
.runlist = pm_runlist_v10,
|
||||
.set_resources = pm_set_resources_vi,
|
||||
.map_queues = pm_map_queues_v10,
|
||||
.unmap_queues = pm_unmap_queues_v10,
|
||||
.query_status = pm_query_status_v10,
|
||||
.release_mem = pm_release_mem_v10,
|
||||
.map_process_size = sizeof(struct pm4_mes_map_process),
|
||||
.runlist_size = sizeof(struct pm4_mes_runlist),
|
||||
.set_resources_size = sizeof(struct pm4_mes_set_resources),
|
||||
.map_queues_size = sizeof(struct pm4_mes_map_queues),
|
||||
.unmap_queues_size = sizeof(struct pm4_mes_unmap_queues),
|
||||
.query_status_size = sizeof(struct pm4_mes_query_status),
|
||||
.release_mem_size = sizeof(struct pm4_mec_release_mem)
|
||||
};
|
||||
|
@ -374,7 +374,6 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
|
||||
|
||||
switch (type) {
|
||||
case KFD_MQD_TYPE_CP:
|
||||
case KFD_MQD_TYPE_COMPUTE:
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd;
|
||||
mqd->free_mqd = free_mqd;
|
||||
@ -401,7 +400,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type,
|
||||
#endif
|
||||
break;
|
||||
case KFD_MQD_TYPE_DIQ:
|
||||
mqd->allocate_mqd = allocate_hiq_mqd;
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd;
|
||||
mqd->load_mqd = load_mqd;
|
||||
@ -442,7 +441,7 @@ struct mqd_manager *mqd_manager_init_cik_hawaii(enum KFD_MQD_TYPE type,
|
||||
mqd = mqd_manager_init_cik(type, dev);
|
||||
if (!mqd)
|
||||
return NULL;
|
||||
if ((type == KFD_MQD_TYPE_CP) || (type == KFD_MQD_TYPE_COMPUTE))
|
||||
if (type == KFD_MQD_TYPE_CP)
|
||||
mqd->update_mqd = update_mqd_hawaii;
|
||||
return mqd;
|
||||
}
|
||||
|
@ -66,6 +66,12 @@ static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
m->compute_static_thread_mgmt_se3);
|
||||
}
|
||||
|
||||
static void set_priority(struct v10_compute_mqd *m, struct queue_properties *q)
|
||||
{
|
||||
m->cp_hqd_pipe_priority = pipe_priority_map[q->priority];
|
||||
m->cp_hqd_queue_priority = q->priority;
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
@ -109,9 +115,6 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
1 << CP_HQD_QUANTUM__QUANTUM_SCALE__SHIFT |
|
||||
10 << CP_HQD_QUANTUM__QUANTUM_DURATION__SHIFT;
|
||||
|
||||
m->cp_hqd_pipe_priority = 1;
|
||||
m->cp_hqd_queue_priority = 15;
|
||||
|
||||
if (q->format == KFD_QUEUE_FORMAT_AQL) {
|
||||
m->cp_hqd_aql_control =
|
||||
1 << CP_HQD_AQL_CONTROL__CONTROL0__SHIFT;
|
||||
@ -208,11 +211,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
m->cp_hqd_ctx_save_control = 0;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = (q->queue_size > 0 &&
|
||||
q->queue_address != 0 &&
|
||||
q->queue_percent > 0 &&
|
||||
!q->is_evicted);
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
}
|
||||
|
||||
static int destroy_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -247,18 +248,22 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
|
||||
/* Control stack is located one page after MQD. */
|
||||
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
/* Control stack is written backwards, while workgroup context data
|
||||
* is written forwards. Both starts from m->cp_hqd_cntl_stack_size.
|
||||
* Current position is at m->cp_hqd_cntl_stack_offset and
|
||||
* m->cp_hqd_wg_state_offset, respectively.
|
||||
*/
|
||||
*ctl_stack_used_size = m->cp_hqd_cntl_stack_size -
|
||||
m->cp_hqd_cntl_stack_offset;
|
||||
*save_area_used_size = m->cp_hqd_wg_state_offset -
|
||||
m->cp_hqd_cntl_stack_size;
|
||||
|
||||
if (copy_to_user(ctl_stack, mqd_ctl_stack, m->cp_hqd_cntl_stack_size))
|
||||
return -EFAULT;
|
||||
/* Control stack is not copied to user mode for GFXv10 because
|
||||
* it's part of the context save area that is already
|
||||
* accessible to user mode
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -277,18 +282,6 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
1 << CP_HQD_PQ_CONTROL__KMD_QUEUE__SHIFT;
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
|
||||
update_mqd(mm, mqd, q);
|
||||
|
||||
/* TODO: what's the point? update_mqd already does this. */
|
||||
m = get_mqd(mqd);
|
||||
m->cp_hqd_vmid = q->vmid;
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *q)
|
||||
@ -340,11 +333,7 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
m->sdma_queue_id = q->sdma_queue_id;
|
||||
m->sdmax_rlcx_dummy_reg = SDMA_RLC_DUMMY_DEFAULT;
|
||||
|
||||
|
||||
q->is_active = (q->queue_size > 0 &&
|
||||
q->queue_address != 0 &&
|
||||
q->queue_percent > 0 &&
|
||||
!q->is_evicted);
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -392,7 +381,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
|
||||
if (WARN_ON(type >= KFD_MQD_TYPE_MAX))
|
||||
return NULL;
|
||||
|
||||
mqd = kzalloc(sizeof(*mqd), GFP_NOIO);
|
||||
mqd = kzalloc(sizeof(*mqd), GFP_KERNEL);
|
||||
if (!mqd)
|
||||
return NULL;
|
||||
|
||||
@ -400,7 +389,6 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
|
||||
|
||||
switch (type) {
|
||||
case KFD_MQD_TYPE_CP:
|
||||
case KFD_MQD_TYPE_COMPUTE:
|
||||
pr_debug("%s@%i\n", __func__, __LINE__);
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd;
|
||||
@ -422,7 +410,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd_hiq_sdma;
|
||||
mqd->load_mqd = load_mqd;
|
||||
mqd->update_mqd = update_mqd_hiq;
|
||||
mqd->update_mqd = update_mqd;
|
||||
mqd->destroy_mqd = destroy_mqd;
|
||||
mqd->is_occupied = is_occupied;
|
||||
mqd->mqd_size = sizeof(struct v10_compute_mqd);
|
||||
@ -432,11 +420,11 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type,
|
||||
pr_debug("%s@%i\n", __func__, __LINE__);
|
||||
break;
|
||||
case KFD_MQD_TYPE_DIQ:
|
||||
mqd->allocate_mqd = allocate_hiq_mqd;
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd;
|
||||
mqd->load_mqd = load_mqd;
|
||||
mqd->update_mqd = update_mqd_hiq;
|
||||
mqd->update_mqd = update_mqd;
|
||||
mqd->destroy_mqd = destroy_mqd;
|
||||
mqd->is_occupied = is_occupied;
|
||||
mqd->mqd_size = sizeof(struct v10_compute_mqd);
|
||||
|
@ -92,7 +92,7 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_dev *kfd,
|
||||
* instead of sub-allocation function.
|
||||
*/
|
||||
if (kfd->cwsr_enabled && (q->type == KFD_QUEUE_TYPE_COMPUTE)) {
|
||||
mqd_mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_NOIO);
|
||||
mqd_mem_obj = kzalloc(sizeof(struct kfd_mem_obj), GFP_KERNEL);
|
||||
if (!mqd_mem_obj)
|
||||
return NULL;
|
||||
retval = amdgpu_amdkfd_alloc_gtt_mem(kfd->kgd,
|
||||
@ -302,7 +302,8 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
*ctl_stack_used_size = m->cp_hqd_cntl_stack_size -
|
||||
m->cp_hqd_cntl_stack_offset;
|
||||
*save_area_used_size = m->cp_hqd_wg_state_offset;
|
||||
*save_area_used_size = m->cp_hqd_wg_state_offset -
|
||||
m->cp_hqd_cntl_stack_size;
|
||||
|
||||
if (copy_to_user(ctl_stack, mqd_ctl_stack, m->cp_hqd_cntl_stack_size))
|
||||
return -EFAULT;
|
||||
@ -324,18 +325,6 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
1 << CP_HQD_PQ_CONTROL__KMD_QUEUE__SHIFT;
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
|
||||
update_mqd(mm, mqd, q);
|
||||
|
||||
/* TODO: what's the point? update_mqd already does this. */
|
||||
m = get_mqd(mqd);
|
||||
m->cp_hqd_vmid = q->vmid;
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr,
|
||||
struct queue_properties *q)
|
||||
@ -443,7 +432,6 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
|
||||
|
||||
switch (type) {
|
||||
case KFD_MQD_TYPE_CP:
|
||||
case KFD_MQD_TYPE_COMPUTE:
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd;
|
||||
mqd->free_mqd = free_mqd;
|
||||
@ -462,7 +450,7 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd_hiq_sdma;
|
||||
mqd->load_mqd = load_mqd;
|
||||
mqd->update_mqd = update_mqd_hiq;
|
||||
mqd->update_mqd = update_mqd;
|
||||
mqd->destroy_mqd = destroy_mqd;
|
||||
mqd->is_occupied = is_occupied;
|
||||
mqd->mqd_size = sizeof(struct v9_mqd);
|
||||
@ -471,11 +459,11 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
|
||||
#endif
|
||||
break;
|
||||
case KFD_MQD_TYPE_DIQ:
|
||||
mqd->allocate_mqd = allocate_hiq_mqd;
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd;
|
||||
mqd->load_mqd = load_mqd;
|
||||
mqd->update_mqd = update_mqd_hiq;
|
||||
mqd->update_mqd = update_mqd;
|
||||
mqd->destroy_mqd = destroy_mqd;
|
||||
mqd->is_occupied = is_occupied;
|
||||
mqd->mqd_size = sizeof(struct v9_mqd);
|
||||
|
@ -312,11 +312,7 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
__update_mqd(mm, mqd, q, MTYPE_UC, 0);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->cp_hqd_vmid = q->vmid;
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
@ -425,7 +421,6 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
|
||||
|
||||
switch (type) {
|
||||
case KFD_MQD_TYPE_CP:
|
||||
case KFD_MQD_TYPE_COMPUTE:
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd;
|
||||
mqd->free_mqd = free_mqd;
|
||||
@ -453,7 +448,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type,
|
||||
#endif
|
||||
break;
|
||||
case KFD_MQD_TYPE_DIQ:
|
||||
mqd->allocate_mqd = allocate_hiq_mqd;
|
||||
mqd->allocate_mqd = allocate_mqd;
|
||||
mqd->init_mqd = init_mqd_hiq;
|
||||
mqd->free_mqd = free_mqd;
|
||||
mqd->load_mqd = load_mqd;
|
||||
@ -494,7 +489,7 @@ struct mqd_manager *mqd_manager_init_vi_tonga(enum KFD_MQD_TYPE type,
|
||||
mqd = mqd_manager_init_vi(type, dev);
|
||||
if (!mqd)
|
||||
return NULL;
|
||||
if ((type == KFD_MQD_TYPE_CP) || (type == KFD_MQD_TYPE_COMPUTE))
|
||||
if (type == KFD_MQD_TYPE_CP)
|
||||
mqd->update_mqd = update_mqd_tonga;
|
||||
return mqd;
|
||||
}
|
||||
|
@ -241,12 +241,10 @@ int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm)
|
||||
case CHIP_RAVEN:
|
||||
case CHIP_RENOIR:
|
||||
case CHIP_ARCTURUS:
|
||||
pm->pmf = &kfd_v9_pm_funcs;
|
||||
break;
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_NAVI14:
|
||||
pm->pmf = &kfd_v10_pm_funcs;
|
||||
pm->pmf = &kfd_v9_pm_funcs;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "Unexpected ASIC family %u",
|
||||
@ -280,7 +278,7 @@ int pm_send_set_resources(struct packet_manager *pm,
|
||||
|
||||
size = pm->pmf->set_resources_size;
|
||||
mutex_lock(&pm->lock);
|
||||
pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue,
|
||||
kq_acquire_packet_buffer(pm->priv_queue,
|
||||
size / sizeof(uint32_t),
|
||||
(unsigned int **)&buffer);
|
||||
if (!buffer) {
|
||||
@ -291,9 +289,9 @@ int pm_send_set_resources(struct packet_manager *pm,
|
||||
|
||||
retval = pm->pmf->set_resources(pm, buffer, res);
|
||||
if (!retval)
|
||||
pm->priv_queue->ops.submit_packet(pm->priv_queue);
|
||||
kq_submit_packet(pm->priv_queue);
|
||||
else
|
||||
pm->priv_queue->ops.rollback_packet(pm->priv_queue);
|
||||
kq_rollback_packet(pm->priv_queue);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pm->lock);
|
||||
@ -318,7 +316,7 @@ int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues)
|
||||
packet_size_dwords = pm->pmf->runlist_size / sizeof(uint32_t);
|
||||
mutex_lock(&pm->lock);
|
||||
|
||||
retval = pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue,
|
||||
retval = kq_acquire_packet_buffer(pm->priv_queue,
|
||||
packet_size_dwords, &rl_buffer);
|
||||
if (retval)
|
||||
goto fail_acquire_packet_buffer;
|
||||
@ -328,14 +326,14 @@ int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues)
|
||||
if (retval)
|
||||
goto fail_create_runlist;
|
||||
|
||||
pm->priv_queue->ops.submit_packet(pm->priv_queue);
|
||||
kq_submit_packet(pm->priv_queue);
|
||||
|
||||
mutex_unlock(&pm->lock);
|
||||
|
||||
return retval;
|
||||
|
||||
fail_create_runlist:
|
||||
pm->priv_queue->ops.rollback_packet(pm->priv_queue);
|
||||
kq_rollback_packet(pm->priv_queue);
|
||||
fail_acquire_packet_buffer:
|
||||
mutex_unlock(&pm->lock);
|
||||
fail_create_runlist_ib:
|
||||
@ -354,7 +352,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address,
|
||||
|
||||
size = pm->pmf->query_status_size;
|
||||
mutex_lock(&pm->lock);
|
||||
pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue,
|
||||
kq_acquire_packet_buffer(pm->priv_queue,
|
||||
size / sizeof(uint32_t), (unsigned int **)&buffer);
|
||||
if (!buffer) {
|
||||
pr_err("Failed to allocate buffer on kernel queue\n");
|
||||
@ -364,9 +362,9 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address,
|
||||
|
||||
retval = pm->pmf->query_status(pm, buffer, fence_address, fence_value);
|
||||
if (!retval)
|
||||
pm->priv_queue->ops.submit_packet(pm->priv_queue);
|
||||
kq_submit_packet(pm->priv_queue);
|
||||
else
|
||||
pm->priv_queue->ops.rollback_packet(pm->priv_queue);
|
||||
kq_rollback_packet(pm->priv_queue);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pm->lock);
|
||||
@ -383,7 +381,7 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type,
|
||||
|
||||
size = pm->pmf->unmap_queues_size;
|
||||
mutex_lock(&pm->lock);
|
||||
pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue,
|
||||
kq_acquire_packet_buffer(pm->priv_queue,
|
||||
size / sizeof(uint32_t), (unsigned int **)&buffer);
|
||||
if (!buffer) {
|
||||
pr_err("Failed to allocate buffer on kernel queue\n");
|
||||
@ -394,9 +392,9 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type,
|
||||
retval = pm->pmf->unmap_queues(pm, buffer, type, filter, filter_param,
|
||||
reset, sdma_engine);
|
||||
if (!retval)
|
||||
pm->priv_queue->ops.submit_packet(pm->priv_queue);
|
||||
kq_submit_packet(pm->priv_queue);
|
||||
else
|
||||
pm->priv_queue->ops.rollback_packet(pm->priv_queue);
|
||||
kq_rollback_packet(pm->priv_queue);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pm->lock);
|
||||
@ -441,7 +439,7 @@ int pm_debugfs_hang_hws(struct packet_manager *pm)
|
||||
|
||||
size = pm->pmf->query_status_size;
|
||||
mutex_lock(&pm->lock);
|
||||
pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue,
|
||||
kq_acquire_packet_buffer(pm->priv_queue,
|
||||
size / sizeof(uint32_t), (unsigned int **)&buffer);
|
||||
if (!buffer) {
|
||||
pr_err("Failed to allocate buffer on kernel queue\n");
|
||||
@ -449,7 +447,7 @@ int pm_debugfs_hang_hws(struct packet_manager *pm)
|
||||
goto out;
|
||||
}
|
||||
memset(buffer, 0x55, size);
|
||||
pm->priv_queue->ops.submit_packet(pm->priv_queue);
|
||||
kq_submit_packet(pm->priv_queue);
|
||||
|
||||
pr_info("Submitting %x %x %x %x %x %x %x to HIQ to hang the HWS.",
|
||||
buffer[0], buffer[1], buffer[2], buffer[3],
|
||||
|
@ -25,47 +25,7 @@
|
||||
#include "kfd_device_queue_manager.h"
|
||||
#include "kfd_pm4_headers_ai.h"
|
||||
#include "kfd_pm4_opcodes.h"
|
||||
|
||||
static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size);
|
||||
static void uninitialize_v9(struct kernel_queue *kq);
|
||||
static void submit_packet_v9(struct kernel_queue *kq);
|
||||
|
||||
void kernel_queue_init_v9(struct kernel_queue_ops *ops)
|
||||
{
|
||||
ops->initialize = initialize_v9;
|
||||
ops->uninitialize = uninitialize_v9;
|
||||
ops->submit_packet = submit_packet_v9;
|
||||
}
|
||||
|
||||
static bool initialize_v9(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = kfd_gtt_sa_allocate(dev, PAGE_SIZE, &kq->eop_mem);
|
||||
if (retval)
|
||||
return false;
|
||||
|
||||
kq->eop_gpu_addr = kq->eop_mem->gpu_addr;
|
||||
kq->eop_kernel_addr = kq->eop_mem->cpu_ptr;
|
||||
|
||||
memset(kq->eop_kernel_addr, 0, PAGE_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void uninitialize_v9(struct kernel_queue *kq)
|
||||
{
|
||||
kfd_gtt_sa_free(kq->dev, kq->eop_mem);
|
||||
}
|
||||
|
||||
static void submit_packet_v9(struct kernel_queue *kq)
|
||||
{
|
||||
*kq->wptr64_kernel = kq->pending_wptr64;
|
||||
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
|
||||
kq->pending_wptr64);
|
||||
}
|
||||
#include "gc/gc_10_1_0_sh_mask.h"
|
||||
|
||||
static int pm_map_process_v9(struct packet_manager *pm,
|
||||
uint32_t *buffer, struct qcm_process_device *qpd)
|
||||
@ -90,10 +50,17 @@ static int pm_map_process_v9(struct packet_manager *pm,
|
||||
|
||||
packet->sh_mem_config = qpd->sh_mem_config;
|
||||
packet->sh_mem_bases = qpd->sh_mem_bases;
|
||||
packet->sq_shader_tba_lo = lower_32_bits(qpd->tba_addr >> 8);
|
||||
packet->sq_shader_tba_hi = upper_32_bits(qpd->tba_addr >> 8);
|
||||
packet->sq_shader_tma_lo = lower_32_bits(qpd->tma_addr >> 8);
|
||||
packet->sq_shader_tma_hi = upper_32_bits(qpd->tma_addr >> 8);
|
||||
if (qpd->tba_addr) {
|
||||
packet->sq_shader_tba_lo = lower_32_bits(qpd->tba_addr >> 8);
|
||||
/* On GFX9, unlike GFX10, bit TRAP_EN of SQ_SHADER_TBA_HI is
|
||||
* not defined, so setting it won't do any harm.
|
||||
*/
|
||||
packet->sq_shader_tba_hi = upper_32_bits(qpd->tba_addr >> 8)
|
||||
| 1 << SQ_SHADER_TBA_HI__TRAP_EN__SHIFT;
|
||||
|
||||
packet->sq_shader_tma_lo = lower_32_bits(qpd->tma_addr >> 8);
|
||||
packet->sq_shader_tma_hi = upper_32_bits(qpd->tma_addr >> 8);
|
||||
}
|
||||
|
||||
packet->gds_addr_lo = lower_32_bits(qpd->gds_context_area);
|
||||
packet->gds_addr_hi = upper_32_bits(qpd->gds_context_area);
|
||||
@ -341,35 +308,6 @@ static int pm_query_status_v9(struct packet_manager *pm, uint32_t *buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int pm_release_mem_v9(uint64_t gpu_addr, uint32_t *buffer)
|
||||
{
|
||||
struct pm4_mec_release_mem *packet;
|
||||
|
||||
packet = (struct pm4_mec_release_mem *)buffer;
|
||||
memset(buffer, 0, sizeof(struct pm4_mec_release_mem));
|
||||
|
||||
packet->header.u32All = pm_build_pm4_header(IT_RELEASE_MEM,
|
||||
sizeof(struct pm4_mec_release_mem));
|
||||
|
||||
packet->bitfields2.event_type = CACHE_FLUSH_AND_INV_TS_EVENT;
|
||||
packet->bitfields2.event_index = event_index__mec_release_mem__end_of_pipe;
|
||||
packet->bitfields2.tcl1_action_ena = 1;
|
||||
packet->bitfields2.tc_action_ena = 1;
|
||||
packet->bitfields2.cache_policy = cache_policy__mec_release_mem__lru;
|
||||
|
||||
packet->bitfields3.data_sel = data_sel__mec_release_mem__send_32_bit_low;
|
||||
packet->bitfields3.int_sel =
|
||||
int_sel__mec_release_mem__send_interrupt_after_write_confirm;
|
||||
|
||||
packet->bitfields4.address_lo_32b = (gpu_addr & 0xffffffff) >> 2;
|
||||
packet->address_hi = upper_32_bits(gpu_addr);
|
||||
|
||||
packet->data_lo = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct packet_manager_funcs kfd_v9_pm_funcs = {
|
||||
.map_process = pm_map_process_v9,
|
||||
.runlist = pm_runlist_v9,
|
||||
@ -377,12 +315,12 @@ const struct packet_manager_funcs kfd_v9_pm_funcs = {
|
||||
.map_queues = pm_map_queues_v9,
|
||||
.unmap_queues = pm_unmap_queues_v9,
|
||||
.query_status = pm_query_status_v9,
|
||||
.release_mem = pm_release_mem_v9,
|
||||
.release_mem = NULL,
|
||||
.map_process_size = sizeof(struct pm4_mes_map_process),
|
||||
.runlist_size = sizeof(struct pm4_mes_runlist),
|
||||
.set_resources_size = sizeof(struct pm4_mes_set_resources),
|
||||
.map_queues_size = sizeof(struct pm4_mes_map_queues),
|
||||
.unmap_queues_size = sizeof(struct pm4_mes_unmap_queues),
|
||||
.query_status_size = sizeof(struct pm4_mes_query_status),
|
||||
.release_mem_size = sizeof(struct pm4_mec_release_mem)
|
||||
.release_mem_size = 0,
|
||||
};
|
@ -26,47 +26,6 @@
|
||||
#include "kfd_pm4_headers_vi.h"
|
||||
#include "kfd_pm4_opcodes.h"
|
||||
|
||||
static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size);
|
||||
static void uninitialize_vi(struct kernel_queue *kq);
|
||||
static void submit_packet_vi(struct kernel_queue *kq);
|
||||
|
||||
void kernel_queue_init_vi(struct kernel_queue_ops *ops)
|
||||
{
|
||||
ops->initialize = initialize_vi;
|
||||
ops->uninitialize = uninitialize_vi;
|
||||
ops->submit_packet = submit_packet_vi;
|
||||
}
|
||||
|
||||
static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
enum kfd_queue_type type, unsigned int queue_size)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = kfd_gtt_sa_allocate(dev, PAGE_SIZE, &kq->eop_mem);
|
||||
if (retval != 0)
|
||||
return false;
|
||||
|
||||
kq->eop_gpu_addr = kq->eop_mem->gpu_addr;
|
||||
kq->eop_kernel_addr = kq->eop_mem->cpu_ptr;
|
||||
|
||||
memset(kq->eop_kernel_addr, 0, PAGE_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void uninitialize_vi(struct kernel_queue *kq)
|
||||
{
|
||||
kfd_gtt_sa_free(kq->dev, kq->eop_mem);
|
||||
}
|
||||
|
||||
static void submit_packet_vi(struct kernel_queue *kq)
|
||||
{
|
||||
*kq->wptr_kernel = kq->pending_wptr;
|
||||
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
|
||||
kq->pending_wptr);
|
||||
}
|
||||
|
||||
unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size)
|
||||
{
|
||||
union PM4_MES_TYPE_3_HEADER header;
|
@ -59,24 +59,21 @@
|
||||
* NOTE: struct vm_area_struct.vm_pgoff uses offset in pages. Hence, these
|
||||
* defines are w.r.t to PAGE_SIZE
|
||||
*/
|
||||
#define KFD_MMAP_TYPE_SHIFT (62 - PAGE_SHIFT)
|
||||
#define KFD_MMAP_TYPE_SHIFT 62
|
||||
#define KFD_MMAP_TYPE_MASK (0x3ULL << KFD_MMAP_TYPE_SHIFT)
|
||||
#define KFD_MMAP_TYPE_DOORBELL (0x3ULL << KFD_MMAP_TYPE_SHIFT)
|
||||
#define KFD_MMAP_TYPE_EVENTS (0x2ULL << KFD_MMAP_TYPE_SHIFT)
|
||||
#define KFD_MMAP_TYPE_RESERVED_MEM (0x1ULL << KFD_MMAP_TYPE_SHIFT)
|
||||
#define KFD_MMAP_TYPE_MMIO (0x0ULL << KFD_MMAP_TYPE_SHIFT)
|
||||
|
||||
#define KFD_MMAP_GPU_ID_SHIFT (46 - PAGE_SHIFT)
|
||||
#define KFD_MMAP_GPU_ID_SHIFT 46
|
||||
#define KFD_MMAP_GPU_ID_MASK (((1ULL << KFD_GPU_ID_HASH_WIDTH) - 1) \
|
||||
<< KFD_MMAP_GPU_ID_SHIFT)
|
||||
#define KFD_MMAP_GPU_ID(gpu_id) ((((uint64_t)gpu_id) << KFD_MMAP_GPU_ID_SHIFT)\
|
||||
& KFD_MMAP_GPU_ID_MASK)
|
||||
#define KFD_MMAP_GPU_ID_GET(offset) ((offset & KFD_MMAP_GPU_ID_MASK) \
|
||||
#define KFD_MMAP_GET_GPU_ID(offset) ((offset & KFD_MMAP_GPU_ID_MASK) \
|
||||
>> KFD_MMAP_GPU_ID_SHIFT)
|
||||
|
||||
#define KFD_MMAP_OFFSET_VALUE_MASK (0x3FFFFFFFFFFFULL >> PAGE_SHIFT)
|
||||
#define KFD_MMAP_OFFSET_VALUE_GET(offset) (offset & KFD_MMAP_OFFSET_VALUE_MASK)
|
||||
|
||||
/*
|
||||
* When working with cp scheduler we should assign the HIQ manually or via
|
||||
* the amdgpu driver to a fixed hqd slot, here are the fixed HIQ hqd slot
|
||||
@ -238,9 +235,10 @@ struct kfd_dev {
|
||||
* KFD. It is aligned for mapping
|
||||
* into user mode
|
||||
*/
|
||||
size_t doorbell_id_offset; /* Doorbell offset (from KFD doorbell
|
||||
* to HW doorbell, GFX reserved some
|
||||
* at the start)
|
||||
size_t doorbell_base_dw_offset; /* Offset from the start of the PCI
|
||||
* doorbell BAR to the first KFD
|
||||
* doorbell in dwords. GFX reserves
|
||||
* the segment before this offset.
|
||||
*/
|
||||
u32 __iomem *doorbell_kernel_ptr; /* This is a pointer for a doorbells
|
||||
* page used by kernel queue
|
||||
@ -510,8 +508,7 @@ struct queue {
|
||||
* Please read the kfd_mqd_manager.h description.
|
||||
*/
|
||||
enum KFD_MQD_TYPE {
|
||||
KFD_MQD_TYPE_COMPUTE = 0, /* for no cp scheduling */
|
||||
KFD_MQD_TYPE_HIQ, /* for hiq */
|
||||
KFD_MQD_TYPE_HIQ = 0, /* for hiq */
|
||||
KFD_MQD_TYPE_CP, /* for cp queues and diq */
|
||||
KFD_MQD_TYPE_SDMA, /* for sdma queues */
|
||||
KFD_MQD_TYPE_DIQ, /* for diq */
|
||||
@ -818,7 +815,7 @@ void kfd_release_kernel_doorbell(struct kfd_dev *kfd, u32 __iomem *db_addr);
|
||||
u32 read_kernel_doorbell(u32 __iomem *db);
|
||||
void write_kernel_doorbell(void __iomem *db, u32 value);
|
||||
void write_kernel_doorbell64(void __iomem *db, u64 value);
|
||||
unsigned int kfd_doorbell_id_to_offset(struct kfd_dev *kfd,
|
||||
unsigned int kfd_get_doorbell_dw_offset_in_bar(struct kfd_dev *kfd,
|
||||
struct kfd_process *process,
|
||||
unsigned int doorbell_id);
|
||||
phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev,
|
||||
@ -904,7 +901,8 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
struct kfd_dev *dev,
|
||||
struct file *f,
|
||||
struct queue_properties *properties,
|
||||
unsigned int *qid);
|
||||
unsigned int *qid,
|
||||
uint32_t *p_doorbell_offset_in_process);
|
||||
int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid);
|
||||
int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p);
|
||||
@ -972,7 +970,6 @@ struct packet_manager_funcs {
|
||||
|
||||
extern const struct packet_manager_funcs kfd_vi_pm_funcs;
|
||||
extern const struct packet_manager_funcs kfd_v9_pm_funcs;
|
||||
extern const struct packet_manager_funcs kfd_v10_pm_funcs;
|
||||
|
||||
int pm_init(struct packet_manager *pm, struct device_queue_manager *dqm);
|
||||
void pm_uninit(struct packet_manager *pm);
|
||||
@ -991,9 +988,6 @@ void pm_release_ib(struct packet_manager *pm);
|
||||
|
||||
/* Following PM funcs can be shared among VI and AI */
|
||||
unsigned int pm_build_pm4_header(unsigned int opcode, size_t packet_size);
|
||||
int pm_set_resources_vi(struct packet_manager *pm, uint32_t *buffer,
|
||||
struct scheduling_resources *res);
|
||||
|
||||
|
||||
uint64_t kfd_get_number_elems(struct kfd_dev *kfd);
|
||||
|
||||
|
@ -560,8 +560,7 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
|
||||
if (!dev->cwsr_enabled || qpd->cwsr_kaddr || qpd->cwsr_base)
|
||||
continue;
|
||||
|
||||
offset = (KFD_MMAP_TYPE_RESERVED_MEM | KFD_MMAP_GPU_ID(dev->id))
|
||||
<< PAGE_SHIFT;
|
||||
offset = KFD_MMAP_TYPE_RESERVED_MEM | KFD_MMAP_GPU_ID(dev->id);
|
||||
qpd->tba_addr = (int64_t)vm_mmap(filep, 0,
|
||||
KFD_CWSR_TBA_TMA_SIZE, PROT_READ | PROT_EXEC,
|
||||
MAP_SHARED, offset);
|
||||
|
@ -162,7 +162,7 @@ void pqm_uninit(struct process_queue_manager *pqm)
|
||||
pqm->queue_slot_bitmap = NULL;
|
||||
}
|
||||
|
||||
static int create_cp_queue(struct process_queue_manager *pqm,
|
||||
static int init_user_queue(struct process_queue_manager *pqm,
|
||||
struct kfd_dev *dev, struct queue **q,
|
||||
struct queue_properties *q_properties,
|
||||
struct file *f, unsigned int qid)
|
||||
@ -192,7 +192,8 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
struct kfd_dev *dev,
|
||||
struct file *f,
|
||||
struct queue_properties *properties,
|
||||
unsigned int *qid)
|
||||
unsigned int *qid,
|
||||
uint32_t *p_doorbell_offset_in_process)
|
||||
{
|
||||
int retval;
|
||||
struct kfd_process_device *pdd;
|
||||
@ -250,7 +251,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
goto err_create_queue;
|
||||
}
|
||||
|
||||
retval = create_cp_queue(pqm, dev, &q, properties, f, *qid);
|
||||
retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
|
||||
if (retval != 0)
|
||||
goto err_create_queue;
|
||||
pqn->q = q;
|
||||
@ -271,7 +272,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
goto err_create_queue;
|
||||
}
|
||||
|
||||
retval = create_cp_queue(pqm, dev, &q, properties, f, *qid);
|
||||
retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
|
||||
if (retval != 0)
|
||||
goto err_create_queue;
|
||||
pqn->q = q;
|
||||
@ -303,12 +304,15 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
goto err_create_queue;
|
||||
}
|
||||
|
||||
if (q)
|
||||
if (q && p_doorbell_offset_in_process)
|
||||
/* Return the doorbell offset within the doorbell page
|
||||
* to the caller so it can be passed up to user mode
|
||||
* (in bytes).
|
||||
* There are always 1024 doorbells per process, so in case
|
||||
* of 8-byte doorbells, there are two doorbell pages per
|
||||
* process.
|
||||
*/
|
||||
properties->doorbell_off =
|
||||
*p_doorbell_offset_in_process =
|
||||
(q->properties.doorbell_off * sizeof(uint32_t)) &
|
||||
(kfd_doorbell_process_slice(dev) - 1);
|
||||
|
||||
|
@ -6,43 +6,16 @@ config DRM_AMD_DC
|
||||
bool "AMD DC - Enable new display engine"
|
||||
default y
|
||||
select SND_HDA_COMPONENT if SND_HDA_CORE
|
||||
select DRM_AMD_DC_DCN1_0 if X86 && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS)
|
||||
select DRM_AMD_DC_DCN if X86 && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS)
|
||||
help
|
||||
Choose this option if you want to use the new display engine
|
||||
support for AMDGPU. This adds required support for Vega and
|
||||
Raven ASICs.
|
||||
|
||||
config DRM_AMD_DC_DCN1_0
|
||||
config DRM_AMD_DC_DCN
|
||||
def_bool n
|
||||
help
|
||||
RV family support for display engine
|
||||
|
||||
config DRM_AMD_DC_DCN2_0
|
||||
bool "DCN 2.0 family"
|
||||
default y
|
||||
depends on DRM_AMD_DC && X86
|
||||
depends on DRM_AMD_DC_DCN1_0
|
||||
help
|
||||
Choose this option if you want to have
|
||||
Navi support for display engine
|
||||
|
||||
config DRM_AMD_DC_DCN2_1
|
||||
bool "DCN 2.1 family"
|
||||
depends on DRM_AMD_DC && X86
|
||||
depends on DRM_AMD_DC_DCN2_0
|
||||
help
|
||||
Choose this option if you want to have
|
||||
Renoir support for display engine
|
||||
|
||||
config DRM_AMD_DC_DSC_SUPPORT
|
||||
bool "DSC support"
|
||||
default y
|
||||
depends on DRM_AMD_DC && X86
|
||||
depends on DRM_AMD_DC_DCN1_0
|
||||
depends on DRM_AMD_DC_DCN2_0
|
||||
help
|
||||
Choose this option if you want to have
|
||||
Dynamic Stream Compression support
|
||||
Raven, Navi and Renoir family support for display engine
|
||||
|
||||
config DRM_AMD_DC_HDCP
|
||||
bool "Enable HDCP support in DC"
|
||||
|
@ -34,6 +34,8 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp
|
||||
endif
|
||||
@ -41,7 +43,7 @@ endif
|
||||
#TODO: remove when Timing Sync feature is complete
|
||||
subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
|
||||
|
||||
DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power
|
||||
DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power dmub/src
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
DAL_LIBS += modules/hdcp
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "dc.h"
|
||||
#include "dc/inc/core_types.h"
|
||||
#include "dal_asic_id.h"
|
||||
#include "dmub/inc/dmub_srv.h"
|
||||
#include "dc/inc/hw/dmcu.h"
|
||||
#include "dc/inc/hw/abm.h"
|
||||
#include "dc/dc_dmub_srv.h"
|
||||
|
||||
#include "vid.h"
|
||||
#include "amdgpu.h"
|
||||
@ -39,6 +43,7 @@
|
||||
#include "amdgpu_dm.h"
|
||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
#include "amdgpu_dm_hdcp.h"
|
||||
#include <drm/drm_hdcp.h>
|
||||
#endif
|
||||
#include "amdgpu_pm.h"
|
||||
|
||||
@ -72,7 +77,7 @@
|
||||
#include <drm/drm_audio_component.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
|
||||
|
||||
#include "dcn/dcn_1_0_offset.h"
|
||||
@ -87,6 +92,9 @@
|
||||
#include "modules/power/power_helpers.h"
|
||||
#include "modules/inc/mod_info_packet.h"
|
||||
|
||||
#define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB);
|
||||
|
||||
#define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin"
|
||||
MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
|
||||
|
||||
@ -478,6 +486,70 @@ static void dm_crtc_high_irq(void *interrupt_params)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/**
|
||||
* dm_dcn_crtc_high_irq() - Handles VStartup interrupt for DCN generation ASICs
|
||||
* @interrupt params - interrupt parameters
|
||||
*
|
||||
* Notify DRM's vblank event handler at VSTARTUP
|
||||
*
|
||||
* Unlike DCE hardware, we trigger the handler at VSTARTUP. at which:
|
||||
* * We are close enough to VUPDATE - the point of no return for hw
|
||||
* * We are in the fixed portion of variable front porch when vrr is enabled
|
||||
* * We are before VUPDATE, where double-buffered vrr registers are swapped
|
||||
*
|
||||
* It is therefore the correct place to signal vblank, send user flip events,
|
||||
* and update VRR.
|
||||
*/
|
||||
static void dm_dcn_crtc_high_irq(void *interrupt_params)
|
||||
{
|
||||
struct common_irq_params *irq_params = interrupt_params;
|
||||
struct amdgpu_device *adev = irq_params->adev;
|
||||
struct amdgpu_crtc *acrtc;
|
||||
struct dm_crtc_state *acrtc_state;
|
||||
unsigned long flags;
|
||||
|
||||
acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
|
||||
|
||||
if (!acrtc)
|
||||
return;
|
||||
|
||||
acrtc_state = to_dm_crtc_state(acrtc->base.state);
|
||||
|
||||
DRM_DEBUG_DRIVER("crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id,
|
||||
amdgpu_dm_vrr_active(acrtc_state));
|
||||
|
||||
amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
|
||||
drm_crtc_handle_vblank(&acrtc->base);
|
||||
|
||||
spin_lock_irqsave(&adev->ddev->event_lock, flags);
|
||||
|
||||
if (acrtc_state->vrr_params.supported &&
|
||||
acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
|
||||
mod_freesync_handle_v_update(
|
||||
adev->dm.freesync_module,
|
||||
acrtc_state->stream,
|
||||
&acrtc_state->vrr_params);
|
||||
|
||||
dc_stream_adjust_vmin_vmax(
|
||||
adev->dm.dc,
|
||||
acrtc_state->stream,
|
||||
&acrtc_state->vrr_params.adjust);
|
||||
}
|
||||
|
||||
if (acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED) {
|
||||
if (acrtc->event) {
|
||||
drm_crtc_send_vblank_event(&acrtc->base, acrtc->event);
|
||||
acrtc->event = NULL;
|
||||
drm_crtc_vblank_put(&acrtc->base);
|
||||
}
|
||||
acrtc->pflip_status = AMDGPU_FLIP_NONE;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dm_set_clockgating_state(void *handle,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
@ -667,12 +739,151 @@ void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
|
||||
}
|
||||
}
|
||||
|
||||
static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
const unsigned int psp_header_bytes = 0x100;
|
||||
const unsigned int psp_footer_bytes = 0x100;
|
||||
const struct dmcub_firmware_header_v1_0 *hdr;
|
||||
struct dmub_srv *dmub_srv = adev->dm.dmub_srv;
|
||||
const struct firmware *dmub_fw = adev->dm.dmub_fw;
|
||||
struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
|
||||
struct abm *abm = adev->dm.dc->res_pool->abm;
|
||||
struct dmub_srv_region_params region_params;
|
||||
struct dmub_srv_region_info region_info;
|
||||
struct dmub_srv_fb_params fb_params;
|
||||
struct dmub_srv_fb_info fb_info;
|
||||
struct dmub_srv_hw_params hw_params;
|
||||
enum dmub_status status;
|
||||
const unsigned char *fw_inst_const, *fw_bss_data;
|
||||
uint32_t i;
|
||||
int r;
|
||||
bool has_hw_support;
|
||||
|
||||
if (!dmub_srv)
|
||||
/* DMUB isn't supported on the ASIC. */
|
||||
return 0;
|
||||
|
||||
if (!dmub_fw) {
|
||||
/* Firmware required for DMUB support. */
|
||||
DRM_ERROR("No firmware provided for DMUB.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status = dmub_srv_has_hw_support(dmub_srv, &has_hw_support);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error checking HW support for DMUB: %d\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!has_hw_support) {
|
||||
DRM_INFO("DMUB unsupported on ASIC\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr = (const struct dmcub_firmware_header_v1_0 *)dmub_fw->data;
|
||||
|
||||
/* Calculate the size of all the regions for the DMUB service. */
|
||||
memset(®ion_params, 0, sizeof(region_params));
|
||||
|
||||
region_params.inst_const_size = le32_to_cpu(hdr->inst_const_bytes) -
|
||||
psp_header_bytes - psp_footer_bytes;
|
||||
region_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes);
|
||||
region_params.vbios_size = adev->dm.dc->ctx->dc_bios->bios_size;
|
||||
|
||||
status = dmub_srv_calc_region_info(dmub_srv, ®ion_params,
|
||||
®ion_info);
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error calculating DMUB region info: %d\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a framebuffer based on the total size of all the regions.
|
||||
* TODO: Move this into GART.
|
||||
*/
|
||||
r = amdgpu_bo_create_kernel(adev, region_info.fb_size, PAGE_SIZE,
|
||||
AMDGPU_GEM_DOMAIN_VRAM, &adev->dm.dmub_bo,
|
||||
&adev->dm.dmub_bo_gpu_addr,
|
||||
&adev->dm.dmub_bo_cpu_addr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Rebase the regions on the framebuffer address. */
|
||||
memset(&fb_params, 0, sizeof(fb_params));
|
||||
fb_params.cpu_addr = adev->dm.dmub_bo_cpu_addr;
|
||||
fb_params.gpu_addr = adev->dm.dmub_bo_gpu_addr;
|
||||
fb_params.region_info = ®ion_info;
|
||||
|
||||
status = dmub_srv_calc_fb_info(dmub_srv, &fb_params, &fb_info);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error calculating DMUB FB info: %d\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_inst_const = dmub_fw->data +
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
|
||||
psp_header_bytes;
|
||||
|
||||
fw_bss_data = dmub_fw->data +
|
||||
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
|
||||
le32_to_cpu(hdr->inst_const_bytes);
|
||||
|
||||
/* Copy firmware and bios info into FB memory. */
|
||||
memcpy(fb_info.fb[DMUB_WINDOW_0_INST_CONST].cpu_addr, fw_inst_const,
|
||||
region_params.inst_const_size);
|
||||
memcpy(fb_info.fb[DMUB_WINDOW_2_BSS_DATA].cpu_addr, fw_bss_data,
|
||||
region_params.bss_data_size);
|
||||
memcpy(fb_info.fb[DMUB_WINDOW_3_VBIOS].cpu_addr,
|
||||
adev->dm.dc->ctx->dc_bios->bios, region_params.vbios_size);
|
||||
|
||||
/* Initialize hardware. */
|
||||
memset(&hw_params, 0, sizeof(hw_params));
|
||||
hw_params.fb_base = adev->gmc.fb_start;
|
||||
hw_params.fb_offset = adev->gmc.aper_base;
|
||||
|
||||
if (dmcu)
|
||||
hw_params.psp_version = dmcu->psp_version;
|
||||
|
||||
for (i = 0; i < fb_info.num_fb; ++i)
|
||||
hw_params.fb[i] = &fb_info.fb[i];
|
||||
|
||||
status = dmub_srv_hw_init(dmub_srv, &hw_params);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error initializing DMUB HW: %d\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Wait for firmware load to finish. */
|
||||
status = dmub_srv_wait_for_auto_load(dmub_srv, 100000);
|
||||
if (status != DMUB_STATUS_OK)
|
||||
DRM_WARN("Wait for DMUB auto-load failed: %d\n", status);
|
||||
|
||||
/* Init DMCU and ABM if available. */
|
||||
if (dmcu && abm) {
|
||||
dmcu->funcs->dmcu_init(dmcu);
|
||||
abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
|
||||
}
|
||||
|
||||
adev->dm.dc->ctx->dmub_srv = dc_dmub_srv_create(adev->dm.dc, dmub_srv);
|
||||
if (!adev->dm.dc->ctx->dmub_srv) {
|
||||
DRM_ERROR("Couldn't allocate DC DMUB server!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DRM_INFO("DMUB hardware initialized: version=0x%08X\n",
|
||||
adev->dm.dmcub_fw_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dc_init_data init_data;
|
||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
struct dc_callback_init init_params;
|
||||
#endif
|
||||
int r;
|
||||
|
||||
adev->dm.ddev = adev->ddev;
|
||||
adev->dm.adev = adev;
|
||||
@ -733,9 +944,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
|
||||
init_data.flags.power_down_display_on_boot = true;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN2_0
|
||||
init_data.soc_bounding_box = adev->dm.soc_bounding_box;
|
||||
#endif
|
||||
|
||||
/* Display Core create. */
|
||||
adev->dm.dc = dc_create(&init_data);
|
||||
@ -749,6 +958,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
|
||||
dc_hardware_init(adev->dm.dc);
|
||||
|
||||
r = dm_dmub_hw_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r);
|
||||
goto error;
|
||||
}
|
||||
|
||||
adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);
|
||||
if (!adev->dm.freesync_module) {
|
||||
DRM_ERROR(
|
||||
@ -821,6 +1036,15 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
|
||||
if (adev->dm.dc)
|
||||
dc_deinit_callbacks(adev->dm.dc);
|
||||
#endif
|
||||
if (adev->dm.dc->ctx->dmub_srv) {
|
||||
dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
|
||||
adev->dm.dc->ctx->dmub_srv = NULL;
|
||||
}
|
||||
|
||||
if (adev->dm.dmub_bo)
|
||||
amdgpu_bo_free_kernel(&adev->dm.dmub_bo,
|
||||
&adev->dm.dmub_bo_gpu_addr,
|
||||
&adev->dm.dmub_bo_cpu_addr);
|
||||
|
||||
/* DC Destroy TODO: Replace destroy DAL */
|
||||
if (adev->dm.dc)
|
||||
@ -932,9 +1156,99 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t amdgpu_dm_dmub_reg_read(void *ctx, uint32_t address)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx;
|
||||
|
||||
return dm_read_reg(adev->dm.dc->ctx, address);
|
||||
}
|
||||
|
||||
static void amdgpu_dm_dmub_reg_write(void *ctx, uint32_t address,
|
||||
uint32_t value)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx;
|
||||
|
||||
return dm_write_reg(adev->dm.dc->ctx, address, value);
|
||||
}
|
||||
|
||||
static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dmub_srv_create_params create_params;
|
||||
const struct dmcub_firmware_header_v1_0 *hdr;
|
||||
const char *fw_name_dmub;
|
||||
enum dmub_asic dmub_asic;
|
||||
enum dmub_status status;
|
||||
int r;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_RENOIR:
|
||||
dmub_asic = DMUB_ASIC_DCN21;
|
||||
fw_name_dmub = FIRMWARE_RENOIR_DMUB;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ASIC doesn't support DMUB. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
adev->dm.dmub_srv = kzalloc(sizeof(*adev->dm.dmub_srv), GFP_KERNEL);
|
||||
if (!adev->dm.dmub_srv) {
|
||||
DRM_ERROR("Failed to allocate DMUB service!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(&create_params, 0, sizeof(create_params));
|
||||
create_params.user_ctx = adev;
|
||||
create_params.funcs.reg_read = amdgpu_dm_dmub_reg_read;
|
||||
create_params.funcs.reg_write = amdgpu_dm_dmub_reg_write;
|
||||
create_params.asic = dmub_asic;
|
||||
|
||||
status = dmub_srv_create(adev->dm.dmub_srv, &create_params);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error creating DMUB service: %d\n", status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = request_firmware_direct(&adev->dm.dmub_fw, fw_name_dmub, adev->dev);
|
||||
if (r) {
|
||||
DRM_ERROR("DMUB firmware loading failed: %d\n", r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = amdgpu_ucode_validate(adev->dm.dmub_fw);
|
||||
if (r) {
|
||||
DRM_ERROR("Couldn't validate DMUB firmware: %d\n", r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
DRM_WARN("Only PSP firmware loading is supported for DMUB\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id =
|
||||
AMDGPU_UCODE_ID_DMCUB;
|
||||
adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].fw = adev->dm.dmub_fw;
|
||||
adev->firmware.fw_size +=
|
||||
ALIGN(le32_to_cpu(hdr->inst_const_bytes), PAGE_SIZE);
|
||||
|
||||
adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
|
||||
|
||||
DRM_INFO("Loading DMUB firmware via PSP: version=0x%08X\n",
|
||||
adev->dm.dmcub_fw_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm_sw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = dm_dmub_sw_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return load_dmcu_fw(adev);
|
||||
}
|
||||
@ -943,6 +1257,16 @@ static int dm_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->dm.dmub_srv) {
|
||||
dmub_srv_destroy(adev->dm.dmub_srv);
|
||||
adev->dm.dmub_srv = NULL;
|
||||
}
|
||||
|
||||
if (adev->dm.dmub_fw) {
|
||||
release_firmware(adev->dm.dmub_fw);
|
||||
adev->dm.dmub_fw = NULL;
|
||||
}
|
||||
|
||||
if(adev->dm.fw_dmcu) {
|
||||
release_firmware(adev->dm.fw_dmcu);
|
||||
adev->dm.fw_dmcu = NULL;
|
||||
@ -1868,7 +2192,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
/* Register IRQ sources and initialize IRQ callbacks */
|
||||
static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -1914,35 +2238,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
|
||||
c_irq_params->irq_src = int_params.irq_source;
|
||||
|
||||
amdgpu_dm_irq_register_interrupt(adev, &int_params,
|
||||
dm_crtc_high_irq, c_irq_params);
|
||||
}
|
||||
|
||||
/* Use VUPDATE_NO_LOCK interrupt on DCN, which seems to correspond to
|
||||
* the regular VUPDATE interrupt on DCE. We want DC_IRQ_SOURCE_VUPDATEx
|
||||
* to trigger at end of each vblank, regardless of state of the lock,
|
||||
* matching DCE behaviour.
|
||||
*/
|
||||
for (i = DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT;
|
||||
i <= DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT + adev->mode_info.num_crtc - 1;
|
||||
i++) {
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->vupdate_irq);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to add vupdate irq id!\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
|
||||
int_params.irq_source =
|
||||
dc_interrupt_to_irq_source(dc, i, 0);
|
||||
|
||||
c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
|
||||
|
||||
c_irq_params->adev = adev;
|
||||
c_irq_params->irq_src = int_params.irq_source;
|
||||
|
||||
amdgpu_dm_irq_register_interrupt(adev, &int_params,
|
||||
dm_vupdate_high_irq, c_irq_params);
|
||||
dm_dcn_crtc_high_irq, c_irq_params);
|
||||
}
|
||||
|
||||
/* Use GRPH_PFLIP interrupt */
|
||||
@ -2457,16 +2753,12 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
case CHIP_RAVEN:
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
case CHIP_NAVI12:
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI14:
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
|
||||
case CHIP_RENOIR:
|
||||
#endif
|
||||
if (dcn10_register_irq_handlers(dm->adev)) {
|
||||
DRM_ERROR("DM: Failed to initialize IRQ\n");
|
||||
goto fail;
|
||||
@ -2612,14 +2904,13 @@ static int dm_early_init(void *handle)
|
||||
adev->mode_info.num_hpd = 6;
|
||||
adev->mode_info.num_dig = 6;
|
||||
break;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
case CHIP_RAVEN:
|
||||
adev->mode_info.num_crtc = 4;
|
||||
adev->mode_info.num_hpd = 4;
|
||||
adev->mode_info.num_dig = 4;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
case CHIP_NAVI10:
|
||||
case CHIP_NAVI12:
|
||||
adev->mode_info.num_crtc = 6;
|
||||
@ -2631,14 +2922,11 @@ static int dm_early_init(void *handle)
|
||||
adev->mode_info.num_hpd = 5;
|
||||
adev->mode_info.num_dig = 5;
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
|
||||
case CHIP_RENOIR:
|
||||
adev->mode_info.num_crtc = 4;
|
||||
adev->mode_info.num_hpd = 4;
|
||||
adev->mode_info.num_dig = 4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
|
||||
return -EINVAL;
|
||||
@ -2931,14 +3219,10 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
|
||||
if (adev->asic_type == CHIP_VEGA10 ||
|
||||
adev->asic_type == CHIP_VEGA12 ||
|
||||
adev->asic_type == CHIP_VEGA20 ||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
|
||||
adev->asic_type == CHIP_NAVI10 ||
|
||||
adev->asic_type == CHIP_NAVI14 ||
|
||||
adev->asic_type == CHIP_NAVI12 ||
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
|
||||
adev->asic_type == CHIP_RENOIR ||
|
||||
#endif
|
||||
adev->asic_type == CHIP_RAVEN) {
|
||||
/* Fill GFX9 params */
|
||||
tiling_info->gfx9.num_pipes =
|
||||
@ -3256,12 +3540,26 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
|
||||
|
||||
static enum dc_color_depth
|
||||
convert_color_depth_from_display_info(const struct drm_connector *connector,
|
||||
const struct drm_connector_state *state)
|
||||
const struct drm_connector_state *state,
|
||||
bool is_y420)
|
||||
{
|
||||
uint8_t bpc = (uint8_t)connector->display_info.bpc;
|
||||
uint8_t bpc;
|
||||
|
||||
/* Assume 8 bpc by default if no bpc is specified. */
|
||||
bpc = bpc ? bpc : 8;
|
||||
if (is_y420) {
|
||||
bpc = 8;
|
||||
|
||||
/* Cap display bpc based on HDMI 2.0 HF-VSDB */
|
||||
if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)
|
||||
bpc = 16;
|
||||
else if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
|
||||
bpc = 12;
|
||||
else if (connector->display_info.hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)
|
||||
bpc = 10;
|
||||
} else {
|
||||
bpc = (uint8_t)connector->display_info.bpc;
|
||||
/* Assume 8 bpc by default if no bpc is specified. */
|
||||
bpc = bpc ? bpc : 8;
|
||||
}
|
||||
|
||||
if (!state)
|
||||
state = connector->state;
|
||||
@ -3432,7 +3730,8 @@ static void fill_stream_properties_from_drm_display_mode(
|
||||
|
||||
timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
|
||||
timing_out->display_color_depth = convert_color_depth_from_display_info(
|
||||
connector, connector_state);
|
||||
connector, connector_state,
|
||||
(timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420));
|
||||
timing_out->scan_type = SCANNING_TYPE_NODATA;
|
||||
timing_out->hdmi_vic = 0;
|
||||
|
||||
@ -3644,10 +3943,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
|
||||
int mode_refresh;
|
||||
int preferred_refresh = 0;
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct dsc_dec_dpcd_caps dsc_caps;
|
||||
uint32_t link_bandwidth_kbps;
|
||||
#endif
|
||||
uint32_t link_bandwidth_kbps;
|
||||
|
||||
struct dc_sink *sink = NULL;
|
||||
if (aconnector == NULL) {
|
||||
@ -3722,16 +4021,18 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
fill_stream_properties_from_drm_display_mode(stream,
|
||||
&mode, &aconnector->base, con_state, old_stream);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
|
||||
stream->timing.flags.DSC = 0;
|
||||
|
||||
if (aconnector->dc_link && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
dc_dsc_parse_dsc_dpcd(aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
|
||||
aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw,
|
||||
&dsc_caps);
|
||||
#endif
|
||||
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
|
||||
dc_link_get_link_cap(aconnector->dc_link));
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dsc_caps.is_dsc_supported)
|
||||
if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
|
||||
&dsc_caps,
|
||||
@ -3740,8 +4041,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
&stream->timing,
|
||||
&stream->timing.dsc_cfg))
|
||||
stream->timing.flags.DSC = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
update_stream_scaling_settings(&mode, dm_state, stream);
|
||||
|
||||
@ -3761,7 +4062,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
|
||||
struct dmcu *dmcu = core_dc->res_pool->dmcu;
|
||||
|
||||
stream->psr_version = dmcu->dmcu_version.psr_version;
|
||||
mod_build_vsc_infopacket(stream, &stream->vsc_infopacket);
|
||||
mod_build_vsc_infopacket(stream,
|
||||
&stream->vsc_infopacket,
|
||||
&stream->use_vsc_sdp_for_colorimetry);
|
||||
}
|
||||
}
|
||||
finish:
|
||||
@ -3852,6 +4155,10 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
|
||||
struct amdgpu_device *adev = crtc->dev->dev_private;
|
||||
int rc;
|
||||
|
||||
/* Do not set vupdate for DCN hardware */
|
||||
if (adev->family > AMDGPU_FAMILY_AI)
|
||||
return 0;
|
||||
|
||||
irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
|
||||
|
||||
rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
|
||||
@ -4095,7 +4402,8 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
|
||||
state->underscan_hborder = 0;
|
||||
state->underscan_vborder = 0;
|
||||
state->base.max_requested_bpc = 8;
|
||||
|
||||
state->vcpi_slots = 0;
|
||||
state->pbn = 0;
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
state->abm_level = amdgpu_dm_abm_level;
|
||||
|
||||
@ -4123,7 +4431,8 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
|
||||
new_state->underscan_enable = state->underscan_enable;
|
||||
new_state->underscan_hborder = state->underscan_hborder;
|
||||
new_state->underscan_vborder = state->underscan_vborder;
|
||||
|
||||
new_state->vcpi_slots = state->vcpi_slots;
|
||||
new_state->pbn = state->pbn;
|
||||
return &new_state->base;
|
||||
}
|
||||
|
||||
@ -4520,10 +4829,68 @@ static void dm_encoder_helper_disable(struct drm_encoder *encoder)
|
||||
|
||||
}
|
||||
|
||||
static int convert_dc_color_depth_into_bpc (enum dc_color_depth display_color_depth)
|
||||
{
|
||||
switch (display_color_depth) {
|
||||
case COLOR_DEPTH_666:
|
||||
return 6;
|
||||
case COLOR_DEPTH_888:
|
||||
return 8;
|
||||
case COLOR_DEPTH_101010:
|
||||
return 10;
|
||||
case COLOR_DEPTH_121212:
|
||||
return 12;
|
||||
case COLOR_DEPTH_141414:
|
||||
return 14;
|
||||
case COLOR_DEPTH_161616:
|
||||
return 16;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_atomic_state *state = crtc_state->state;
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||
struct dm_connector_state *dm_new_connector_state = to_dm_connector_state(conn_state);
|
||||
const struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
struct drm_dp_mst_port *mst_port;
|
||||
enum dc_color_depth color_depth;
|
||||
int clock, bpp = 0;
|
||||
bool is_y420 = false;
|
||||
|
||||
if (!aconnector->port || !aconnector->dc_sink)
|
||||
return 0;
|
||||
|
||||
mst_port = aconnector->port;
|
||||
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||
|
||||
if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
|
||||
return 0;
|
||||
|
||||
if (!state->duplicated) {
|
||||
is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
|
||||
aconnector->force_yuv420_output;
|
||||
color_depth = convert_color_depth_from_display_info(connector, conn_state,
|
||||
is_y420);
|
||||
bpp = convert_dc_color_depth_into_bpc(color_depth) * 3;
|
||||
clock = adjusted_mode->clock;
|
||||
dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp);
|
||||
}
|
||||
dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state,
|
||||
mst_mgr,
|
||||
mst_port,
|
||||
dm_new_connector_state->pbn);
|
||||
if (dm_new_connector_state->vcpi_slots < 0) {
|
||||
DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots);
|
||||
return dm_new_connector_state->vcpi_slots;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5215,7 +5582,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
|
||||
&aconnector->base);
|
||||
#ifdef CONFIG_DRM_AMD_DC_HDCP
|
||||
if (adev->asic_type >= CHIP_RAVEN)
|
||||
drm_connector_attach_content_protection_property(&aconnector->base, false);
|
||||
drm_connector_attach_content_protection_property(&aconnector->base, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -5467,6 +5834,12 @@ static bool is_content_protection_different(struct drm_connector_state *state,
|
||||
{
|
||||
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||
|
||||
if (old_state->hdcp_content_type != state->hdcp_content_type &&
|
||||
state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CP is being re enabled, ignore this */
|
||||
if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
|
||||
state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
|
||||
@ -5495,17 +5868,6 @@ static bool is_content_protection_different(struct drm_connector_state *state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void update_content_protection(struct drm_connector_state *state, const struct drm_connector *connector,
|
||||
struct hdcp_workqueue *hdcp_w)
|
||||
{
|
||||
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
||||
|
||||
if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED)
|
||||
hdcp_add_display(hdcp_w, aconnector->dc_link->link_index, aconnector);
|
||||
else if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
hdcp_remove_display(hdcp_w, aconnector->dc_link->link_index, aconnector->base.index);
|
||||
|
||||
}
|
||||
#endif
|
||||
static void remove_stream(struct amdgpu_device *adev,
|
||||
struct amdgpu_crtc *acrtc,
|
||||
@ -6475,7 +6837,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
}
|
||||
|
||||
if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue))
|
||||
update_content_protection(new_con_state, connector, adev->dm.hdcp_workqueue);
|
||||
hdcp_update_display(
|
||||
adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
|
||||
new_con_state->hdcp_content_type,
|
||||
new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED ? true
|
||||
: false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -7265,7 +7631,7 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
|
||||
int i, j, num_plane, ret = 0;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
|
||||
struct drm_crtc *new_plane_crtc, *old_plane_crtc;
|
||||
struct drm_crtc *new_plane_crtc;
|
||||
struct drm_plane *plane;
|
||||
|
||||
struct drm_crtc *crtc;
|
||||
@ -7311,7 +7677,6 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
|
||||
uint64_t tiling_flags;
|
||||
|
||||
new_plane_crtc = new_plane_state->crtc;
|
||||
old_plane_crtc = old_plane_state->crtc;
|
||||
new_dm_plane_state = to_dm_plane_state(new_plane_state);
|
||||
old_dm_plane_state = to_dm_plane_state(old_plane_state);
|
||||
|
||||
@ -7567,6 +7932,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Perform validation of MST topology in the state*/
|
||||
ret = drm_dp_mst_atomic_check(state);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (state->legacy_cursor_update) {
|
||||
/*
|
||||
* This is a fast cursor update coming from the plane update
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user