mirror of https://gitee.com/openkylin/linux.git
Merge branch 'drm-next-5.1' of git://people.freedesktop.org/~agd5f/linux into drm-next
New stuff for 5.1. amdgpu: - DC bandwidth formula updates - Support for DCC on scanout surfaces - Support for multiple IH rings on soc15 asics - Fix xgmi locking - Add sysfs interface to get pcie usage stats - Simplify DC i2c/aux code - Initial support for BACO on vega10/20 - New runtime SMU feature debug interface - Expand existing sysfs power interfaces to new clock domains - Handle kexec properly - Simplify IH programming - Rework doorbell handling across asics - Drop old CI DPM implementation - DC page flipping fixes - Misc SR-IOV fixes amdkfd: - Simplify the interfaces between amdkfd and amdgpu ttm: - Add a callback to notify the driver when the lru changes sched: - Refactor mirror list handling - Rework hw fence processing Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190125231517.26268-1-alexander.deucher@amd.com
This commit is contained in:
commit
e09191d360
|
@ -57,7 +57,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
|
|||
|
||||
# add asic specific block
|
||||
amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
|
||||
ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
|
||||
dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o
|
||||
|
||||
amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o
|
||||
|
||||
|
|
|
@ -542,6 +542,11 @@ struct amdgpu_asic_funcs {
|
|||
bool (*need_full_reset)(struct amdgpu_device *adev);
|
||||
/* initialize doorbell layout for specific asic*/
|
||||
void (*init_doorbell_index)(struct amdgpu_device *adev);
|
||||
/* PCIe bandwidth usage */
|
||||
void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0,
|
||||
uint64_t *count1);
|
||||
/* do we need to reset the asic at init time (e.g., kexec) */
|
||||
bool (*need_reset_on_init)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -634,7 +639,7 @@ struct amdgpu_nbio_funcs {
|
|||
void (*hdp_flush)(struct amdgpu_device *adev, struct amdgpu_ring *ring);
|
||||
u32 (*get_memsize)(struct amdgpu_device *adev);
|
||||
void (*sdma_doorbell_range)(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index);
|
||||
bool use_doorbell, int doorbell_index, int doorbell_size);
|
||||
void (*enable_doorbell_aperture)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
void (*enable_doorbell_selfring_aperture)(struct amdgpu_device *adev,
|
||||
|
@ -1042,6 +1047,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
|
|||
#define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r))
|
||||
#define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev))
|
||||
#define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((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))
|
||||
|
||||
/* Common functions */
|
||||
bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
const struct kgd2kfd_calls *kgd2kfd;
|
||||
|
||||
static const unsigned int compute_vmid_bitmap = 0xFF00;
|
||||
|
||||
/* Total memory size in system memory and all GPU VRAM. Used to
|
||||
|
@ -47,12 +45,9 @@ int amdgpu_amdkfd_init(void)
|
|||
amdgpu_amdkfd_total_mem_size *= si.mem_unit;
|
||||
|
||||
#ifdef CONFIG_HSA_AMD
|
||||
ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd);
|
||||
if (ret)
|
||||
kgd2kfd = NULL;
|
||||
ret = kgd2kfd_init();
|
||||
amdgpu_amdkfd_gpuvm_init_mem_limits();
|
||||
#else
|
||||
kgd2kfd = NULL;
|
||||
ret = -ENOENT;
|
||||
#endif
|
||||
|
||||
|
@ -61,17 +56,13 @@ int amdgpu_amdkfd_init(void)
|
|||
|
||||
void amdgpu_amdkfd_fini(void)
|
||||
{
|
||||
if (kgd2kfd)
|
||||
kgd2kfd->exit();
|
||||
kgd2kfd_exit();
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
||||
{
|
||||
const struct kfd2kgd_calls *kfd2kgd;
|
||||
|
||||
if (!kgd2kfd)
|
||||
return;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||
case CHIP_KAVERI:
|
||||
|
@ -98,8 +89,8 @@ void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev)
|
|||
return;
|
||||
}
|
||||
|
||||
adev->kfd.dev = kgd2kfd->probe((struct kgd_dev *)adev,
|
||||
adev->pdev, kfd2kgd);
|
||||
adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev,
|
||||
adev->pdev, kfd2kgd);
|
||||
|
||||
if (adev->kfd.dev)
|
||||
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
|
||||
|
@ -182,7 +173,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
|||
&gpu_resources.doorbell_start_offset);
|
||||
|
||||
if (adev->asic_type < CHIP_VEGA10) {
|
||||
kgd2kfd->device_init(adev->kfd.dev, &gpu_resources);
|
||||
kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -197,13 +188,13 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
|||
* can use each doorbell assignment twice.
|
||||
*/
|
||||
gpu_resources.sdma_doorbell[0][i] =
|
||||
adev->doorbell_index.sdma_engine0 + (i >> 1);
|
||||
adev->doorbell_index.sdma_engine[0] + (i >> 1);
|
||||
gpu_resources.sdma_doorbell[0][i+1] =
|
||||
adev->doorbell_index.sdma_engine0 + 0x200 + (i >> 1);
|
||||
adev->doorbell_index.sdma_engine[0] + 0x200 + (i >> 1);
|
||||
gpu_resources.sdma_doorbell[1][i] =
|
||||
adev->doorbell_index.sdma_engine1 + (i >> 1);
|
||||
adev->doorbell_index.sdma_engine[1] + (i >> 1);
|
||||
gpu_resources.sdma_doorbell[1][i+1] =
|
||||
adev->doorbell_index.sdma_engine1 + 0x200 + (i >> 1);
|
||||
adev->doorbell_index.sdma_engine[1] + 0x200 + (i >> 1);
|
||||
}
|
||||
/* Doorbells 0x0e0-0ff and 0x2e0-2ff are reserved for
|
||||
* SDMA, IH and VCN. So don't use them for the CP.
|
||||
|
@ -211,14 +202,14 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
|
|||
gpu_resources.reserved_doorbell_mask = 0x1e0;
|
||||
gpu_resources.reserved_doorbell_val = 0x0e0;
|
||||
|
||||
kgd2kfd->device_init(adev->kfd.dev, &gpu_resources);
|
||||
kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
|
||||
}
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->kfd.dev) {
|
||||
kgd2kfd->device_exit(adev->kfd.dev);
|
||||
kgd2kfd_device_exit(adev->kfd.dev);
|
||||
adev->kfd.dev = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -227,13 +218,13 @@ void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,
|
|||
const void *ih_ring_entry)
|
||||
{
|
||||
if (adev->kfd.dev)
|
||||
kgd2kfd->interrupt(adev->kfd.dev, ih_ring_entry);
|
||||
kgd2kfd_interrupt(adev->kfd.dev, ih_ring_entry);
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_suspend(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->kfd.dev)
|
||||
kgd2kfd->suspend(adev->kfd.dev);
|
||||
kgd2kfd_suspend(adev->kfd.dev);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_resume(struct amdgpu_device *adev)
|
||||
|
@ -241,7 +232,7 @@ int amdgpu_amdkfd_resume(struct amdgpu_device *adev)
|
|||
int r = 0;
|
||||
|
||||
if (adev->kfd.dev)
|
||||
r = kgd2kfd->resume(adev->kfd.dev);
|
||||
r = kgd2kfd_resume(adev->kfd.dev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -251,7 +242,7 @@ int amdgpu_amdkfd_pre_reset(struct amdgpu_device *adev)
|
|||
int r = 0;
|
||||
|
||||
if (adev->kfd.dev)
|
||||
r = kgd2kfd->pre_reset(adev->kfd.dev);
|
||||
r = kgd2kfd_pre_reset(adev->kfd.dev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -261,7 +252,7 @@ int amdgpu_amdkfd_post_reset(struct amdgpu_device *adev)
|
|||
int r = 0;
|
||||
|
||||
if (adev->kfd.dev)
|
||||
r = kgd2kfd->post_reset(adev->kfd.dev);
|
||||
r = kgd2kfd_post_reset(adev->kfd.dev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -619,4 +610,47 @@ struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
const struct kfd2kgd_calls *f2g)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void kgd2kfd_device_exit(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void kgd2kfd_suspend(struct kfd_dev *kfd)
|
||||
{
|
||||
}
|
||||
|
||||
int kgd2kfd_resume(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd2kfd_pre_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "amdgpu_sync.h"
|
||||
#include "amdgpu_vm.h"
|
||||
|
||||
extern const struct kgd2kfd_calls *kgd2kfd;
|
||||
extern uint64_t amdgpu_amdkfd_total_mem_size;
|
||||
|
||||
struct amdgpu_device;
|
||||
|
@ -214,4 +213,22 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd,
|
|||
void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
|
||||
void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo);
|
||||
|
||||
/* KGD2KFD callbacks */
|
||||
int kgd2kfd_init(void);
|
||||
void kgd2kfd_exit(void);
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, struct pci_dev *pdev,
|
||||
const struct kfd2kgd_calls *f2g);
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources);
|
||||
void kgd2kfd_device_exit(struct kfd_dev *kfd);
|
||||
void kgd2kfd_suspend(struct kfd_dev *kfd);
|
||||
int kgd2kfd_resume(struct kfd_dev *kfd);
|
||||
int kgd2kfd_pre_reset(struct kfd_dev *kfd);
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd);
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
|
||||
int kgd2kfd_quiesce_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_resume_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
||||
struct dma_fence *fence);
|
||||
|
||||
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
|
||||
|
|
|
@ -122,7 +122,7 @@ static bool amdkfd_fence_enable_signaling(struct dma_fence *f)
|
|||
if (dma_fence_is_signaled(f))
|
||||
return true;
|
||||
|
||||
if (!kgd2kfd->schedule_evict_and_restore_process(fence->mm, f))
|
||||
if (!kgd2kfd_schedule_evict_and_restore_process(fence->mm, f))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
|
@ -1790,7 +1790,7 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem,
|
|||
evicted_bos = atomic_inc_return(&process_info->evicted_bos);
|
||||
if (evicted_bos == 1) {
|
||||
/* First eviction, stop the queues */
|
||||
r = kgd2kfd->quiesce_mm(mm);
|
||||
r = kgd2kfd_quiesce_mm(mm);
|
||||
if (r)
|
||||
pr_err("Failed to quiesce KFD\n");
|
||||
schedule_delayed_work(&process_info->restore_userptr_work,
|
||||
|
@ -2082,7 +2082,7 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work)
|
|||
evicted_bos)
|
||||
goto unlock_out;
|
||||
evicted_bos = 0;
|
||||
if (kgd2kfd->resume_mm(mm)) {
|
||||
if (kgd2kfd_resume_mm(mm)) {
|
||||
pr_err("%s: Failed to resume KFD\n", __func__);
|
||||
/* No recovery from this failure. Probably the CP is
|
||||
* hanging. No point trying again.
|
||||
|
|
|
@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
|
|||
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||
{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||
{ 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
|
|
@ -1645,7 +1645,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
if (r) {
|
||||
DRM_ERROR("sw_init of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
return r;
|
||||
goto init_failed;
|
||||
}
|
||||
adev->ip_blocks[i].status.sw = true;
|
||||
|
||||
|
@ -1654,17 +1654,17 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
r = amdgpu_device_vram_scratch_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
|
||||
return r;
|
||||
goto init_failed;
|
||||
}
|
||||
r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
|
||||
if (r) {
|
||||
DRM_ERROR("hw_init %d failed %d\n", i, r);
|
||||
return r;
|
||||
goto init_failed;
|
||||
}
|
||||
r = amdgpu_device_wb_init(adev);
|
||||
if (r) {
|
||||
DRM_ERROR("amdgpu_device_wb_init failed %d\n", r);
|
||||
return r;
|
||||
goto init_failed;
|
||||
}
|
||||
adev->ip_blocks[i].status.hw = true;
|
||||
|
||||
|
@ -1675,7 +1675,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
AMDGPU_CSA_SIZE);
|
||||
if (r) {
|
||||
DRM_ERROR("allocate CSA failed %d\n", r);
|
||||
return r;
|
||||
goto init_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1683,28 +1683,32 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
|
|||
|
||||
r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
|
||||
if (r)
|
||||
return r;
|
||||
goto init_failed;
|
||||
|
||||
r = amdgpu_device_ip_hw_init_phase1(adev);
|
||||
if (r)
|
||||
return r;
|
||||
goto init_failed;
|
||||
|
||||
r = amdgpu_device_fw_loading(adev);
|
||||
if (r)
|
||||
return r;
|
||||
goto init_failed;
|
||||
|
||||
r = amdgpu_device_ip_hw_init_phase2(adev);
|
||||
if (r)
|
||||
return r;
|
||||
goto init_failed;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_add_device(adev);
|
||||
amdgpu_amdkfd_device_init(adev);
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
init_failed:
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
if (!r)
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2131,7 +2135,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
|
|||
continue;
|
||||
|
||||
r = block->version->funcs->hw_init(adev);
|
||||
DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
|
||||
DRM_INFO("RE-INIT-early: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -2165,7 +2169,7 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
|
|||
continue;
|
||||
|
||||
r = block->version->funcs->hw_init(adev);
|
||||
DRM_INFO("RE-INIT: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
|
||||
DRM_INFO("RE-INIT-late: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -2546,6 +2550,17 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
/* detect if we are with an SRIOV vbios */
|
||||
amdgpu_device_detect_sriov_bios(adev);
|
||||
|
||||
/* check if we need to reset the asic
|
||||
* E.g., driver was not cleanly unloaded previously, etc.
|
||||
*/
|
||||
if (!amdgpu_sriov_vf(adev) && amdgpu_asic_need_reset_on_init(adev)) {
|
||||
r = amdgpu_asic_reset(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "asic reset on init failed\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Post card if necessary */
|
||||
if (amdgpu_device_need_post(adev)) {
|
||||
if (!adev->bios) {
|
||||
|
@ -2610,6 +2625,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2632,9 +2649,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
|
||||
amdgpu_fbdev_init(adev);
|
||||
|
||||
r = amdgpu_pm_sysfs_init(adev);
|
||||
|
@ -2798,7 +2812,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
|
|||
struct drm_framebuffer *fb = crtc->primary->fb;
|
||||
struct amdgpu_bo *robj;
|
||||
|
||||
if (amdgpu_crtc->cursor_bo) {
|
||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
|
@ -2906,7 +2920,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
|||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||
|
||||
if (amdgpu_crtc->cursor_bo) {
|
||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
|
@ -3226,6 +3240,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
|||
r = amdgpu_ib_ring_tests(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) {
|
||||
atomic_inc(&adev->vram_lost_counter);
|
||||
|
@ -3298,17 +3313,15 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
|||
if (!ring || !ring->sched.thread)
|
||||
continue;
|
||||
|
||||
kthread_park(ring->sched.thread);
|
||||
|
||||
if (job && job->base.sched != &ring->sched)
|
||||
continue;
|
||||
|
||||
drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL);
|
||||
drm_sched_stop(&ring->sched);
|
||||
|
||||
/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
}
|
||||
|
||||
if(job)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
|
||||
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
|
@ -3454,14 +3467,10 @@ static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,
|
|||
if (!ring || !ring->sched.thread)
|
||||
continue;
|
||||
|
||||
/* only need recovery sched of the given job's ring
|
||||
* or all rings (in the case @job is NULL)
|
||||
* after above amdgpu_reset accomplished
|
||||
*/
|
||||
if ((!job || job->base.sched == &ring->sched) && !adev->asic_reset_res)
|
||||
drm_sched_job_recovery(&ring->sched);
|
||||
if (!adev->asic_reset_res)
|
||||
drm_sched_resubmit_jobs(&ring->sched);
|
||||
|
||||
kthread_unpark(ring->sched.thread);
|
||||
drm_sched_start(&ring->sched, !adev->asic_reset_res);
|
||||
}
|
||||
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
|
@ -3521,9 +3530,9 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
* by different nodes. No point also since the one node already executing
|
||||
* reset will also reset all the other nodes in the hive.
|
||||
*/
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
hive = amdgpu_get_xgmi_hive(adev, 0);
|
||||
if (hive && adev->gmc.xgmi.num_physical_nodes > 1 &&
|
||||
!mutex_trylock(&hive->hive_lock))
|
||||
!mutex_trylock(&hive->reset_lock))
|
||||
return 0;
|
||||
|
||||
/* Start with adev pre asic reset first for soft reset check.*/
|
||||
|
@ -3602,7 +3611,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
if (hive && adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
mutex_unlock(&hive->reset_lock);
|
||||
|
||||
if (r)
|
||||
dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
|
||||
|
|
|
@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
|
||||
if (unlikely(r != 0)) {
|
||||
DRM_ERROR("failed to pin new abo buffer before flip\n");
|
||||
goto unreserve;
|
||||
if (!adev->enable_virtual_display) {
|
||||
r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
|
||||
if (unlikely(r != 0)) {
|
||||
DRM_ERROR("failed to pin new abo buffer before flip\n");
|
||||
goto unreserve;
|
||||
}
|
||||
}
|
||||
|
||||
r = amdgpu_ttm_alloc_gart(&new_abo->tbo);
|
||||
|
@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);
|
||||
amdgpu_bo_unreserve(new_abo);
|
||||
|
||||
work->base = amdgpu_bo_gpu_offset(new_abo);
|
||||
if (!adev->enable_virtual_display)
|
||||
work->base = amdgpu_bo_gpu_offset(new_abo);
|
||||
work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
|
||||
amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
|
||||
|
||||
|
@ -242,9 +245,10 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
goto cleanup;
|
||||
}
|
||||
unpin:
|
||||
if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
|
||||
DRM_ERROR("failed to unpin new abo in error path\n");
|
||||
}
|
||||
if (!adev->enable_virtual_display)
|
||||
if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
|
||||
DRM_ERROR("failed to unpin new abo in error path\n");
|
||||
|
||||
unreserve:
|
||||
amdgpu_bo_unreserve(new_abo);
|
||||
|
||||
|
|
|
@ -51,14 +51,7 @@ struct amdgpu_doorbell_index {
|
|||
uint32_t userqueue_start;
|
||||
uint32_t userqueue_end;
|
||||
uint32_t gfx_ring0;
|
||||
uint32_t sdma_engine0;
|
||||
uint32_t sdma_engine1;
|
||||
uint32_t sdma_engine2;
|
||||
uint32_t sdma_engine3;
|
||||
uint32_t sdma_engine4;
|
||||
uint32_t sdma_engine5;
|
||||
uint32_t sdma_engine6;
|
||||
uint32_t sdma_engine7;
|
||||
uint32_t sdma_engine[8];
|
||||
uint32_t ih;
|
||||
union {
|
||||
struct {
|
||||
|
@ -79,6 +72,8 @@ struct amdgpu_doorbell_index {
|
|||
} uvd_vce;
|
||||
};
|
||||
uint32_t max_assignment;
|
||||
/* Per engine SDMA doorbell size in dword */
|
||||
uint32_t sdma_doorbell_range;
|
||||
};
|
||||
|
||||
typedef enum _AMDGPU_DOORBELL_ASSIGNMENT
|
||||
|
|
|
@ -364,6 +364,14 @@ enum amdgpu_pcie_gen {
|
|||
((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
|
||||
(adev)->powerplay.pp_handle))
|
||||
|
||||
#define amdgpu_dpm_get_ppfeature_status(adev, buf) \
|
||||
((adev)->powerplay.pp_funcs->get_ppfeature_status(\
|
||||
(adev)->powerplay.pp_handle, (buf)))
|
||||
|
||||
#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \
|
||||
((adev)->powerplay.pp_funcs->set_ppfeature_status(\
|
||||
(adev)->powerplay.pp_handle, (ppfeatures)))
|
||||
|
||||
struct amdgpu_dpm {
|
||||
struct amdgpu_ps *ps;
|
||||
/* number of valid power states */
|
||||
|
|
|
@ -202,12 +202,12 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
|
|||
amdgpu_asic_flush_hdp(adev, ring);
|
||||
}
|
||||
|
||||
if (need_ctx_switch)
|
||||
status |= AMDGPU_HAVE_CTX_SWITCH;
|
||||
|
||||
skip_preamble = ring->current_ctx == fence_ctx;
|
||||
if (job && ring->funcs->emit_cntxcntl) {
|
||||
if (need_ctx_switch)
|
||||
status |= AMDGPU_HAVE_CTX_SWITCH;
|
||||
status |= job->preamble_status;
|
||||
|
||||
amdgpu_ring_emit_cntxcntl(ring, status);
|
||||
}
|
||||
|
||||
|
@ -221,8 +221,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
|
|||
!amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */
|
||||
continue;
|
||||
|
||||
amdgpu_ring_emit_ib(ring, job, ib, need_ctx_switch);
|
||||
need_ctx_switch = false;
|
||||
amdgpu_ring_emit_ib(ring, job, ib, status);
|
||||
status &= ~AMDGPU_HAVE_CTX_SWITCH;
|
||||
}
|
||||
|
||||
if (ring->funcs->emit_tmz)
|
||||
|
|
|
@ -52,6 +52,8 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
ih->use_bus_addr = use_bus_addr;
|
||||
|
||||
if (use_bus_addr) {
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
if (ih->ring)
|
||||
return 0;
|
||||
|
||||
|
@ -59,21 +61,26 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
* add them to the end of the ring allocation.
|
||||
*/
|
||||
ih->ring = dma_alloc_coherent(adev->dev, ih->ring_size + 8,
|
||||
&ih->rb_dma_addr, GFP_KERNEL);
|
||||
&dma_addr, GFP_KERNEL);
|
||||
if (ih->ring == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset((void *)ih->ring, 0, ih->ring_size + 8);
|
||||
ih->wptr_offs = (ih->ring_size / 4) + 0;
|
||||
ih->rptr_offs = (ih->ring_size / 4) + 1;
|
||||
ih->gpu_addr = dma_addr;
|
||||
ih->wptr_addr = dma_addr + ih->ring_size;
|
||||
ih->wptr_cpu = &ih->ring[ih->ring_size / 4];
|
||||
ih->rptr_addr = dma_addr + ih->ring_size + 4;
|
||||
ih->rptr_cpu = &ih->ring[(ih->ring_size / 4) + 1];
|
||||
} else {
|
||||
r = amdgpu_device_wb_get(adev, &ih->wptr_offs);
|
||||
unsigned wptr_offs, rptr_offs;
|
||||
|
||||
r = amdgpu_device_wb_get(adev, &wptr_offs);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_device_wb_get(adev, &ih->rptr_offs);
|
||||
r = amdgpu_device_wb_get(adev, &rptr_offs);
|
||||
if (r) {
|
||||
amdgpu_device_wb_free(adev, ih->wptr_offs);
|
||||
amdgpu_device_wb_free(adev, wptr_offs);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -82,10 +89,15 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
&ih->ring_obj, &ih->gpu_addr,
|
||||
(void **)&ih->ring);
|
||||
if (r) {
|
||||
amdgpu_device_wb_free(adev, ih->rptr_offs);
|
||||
amdgpu_device_wb_free(adev, ih->wptr_offs);
|
||||
amdgpu_device_wb_free(adev, rptr_offs);
|
||||
amdgpu_device_wb_free(adev, wptr_offs);
|
||||
return r;
|
||||
}
|
||||
|
||||
ih->wptr_addr = adev->wb.gpu_addr + wptr_offs * 4;
|
||||
ih->wptr_cpu = &adev->wb.wb[wptr_offs];
|
||||
ih->rptr_addr = adev->wb.gpu_addr + rptr_offs * 4;
|
||||
ih->rptr_cpu = &adev->wb.wb[rptr_offs];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -109,13 +121,13 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
|
|||
* add them to the end of the ring allocation.
|
||||
*/
|
||||
dma_free_coherent(adev->dev, ih->ring_size + 8,
|
||||
(void *)ih->ring, ih->rb_dma_addr);
|
||||
(void *)ih->ring, ih->gpu_addr);
|
||||
ih->ring = NULL;
|
||||
} else {
|
||||
amdgpu_bo_free_kernel(&ih->ring_obj, &ih->gpu_addr,
|
||||
(void **)&ih->ring);
|
||||
amdgpu_device_wb_free(adev, ih->wptr_offs);
|
||||
amdgpu_device_wb_free(adev, ih->rptr_offs);
|
||||
amdgpu_device_wb_free(adev, (ih->wptr_addr - ih->gpu_addr) / 4);
|
||||
amdgpu_device_wb_free(adev, (ih->rptr_addr - ih->gpu_addr) / 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,7 +149,7 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
if (!ih->enabled || adev->shutdown)
|
||||
return IRQ_NONE;
|
||||
|
||||
wptr = amdgpu_ih_get_wptr(adev);
|
||||
wptr = amdgpu_ih_get_wptr(adev, ih);
|
||||
|
||||
restart_ih:
|
||||
/* is somebody else already processing irqs? */
|
||||
|
@ -154,11 +166,11 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
|||
ih->rptr &= ih->ptr_mask;
|
||||
}
|
||||
|
||||
amdgpu_ih_set_rptr(adev);
|
||||
amdgpu_ih_set_rptr(adev, ih);
|
||||
atomic_set(&ih->lock, 0);
|
||||
|
||||
/* make sure wptr hasn't changed while processing */
|
||||
wptr = amdgpu_ih_get_wptr(adev);
|
||||
wptr = amdgpu_ih_get_wptr(adev, ih);
|
||||
if (wptr != ih->rptr)
|
||||
goto restart_ih;
|
||||
|
||||
|
|
|
@ -31,34 +31,40 @@ struct amdgpu_iv_entry;
|
|||
* R6xx+ IH ring
|
||||
*/
|
||||
struct amdgpu_ih_ring {
|
||||
struct amdgpu_bo *ring_obj;
|
||||
volatile uint32_t *ring;
|
||||
unsigned rptr;
|
||||
unsigned ring_size;
|
||||
uint64_t gpu_addr;
|
||||
uint32_t ptr_mask;
|
||||
atomic_t lock;
|
||||
bool enabled;
|
||||
unsigned wptr_offs;
|
||||
unsigned rptr_offs;
|
||||
u32 doorbell_index;
|
||||
bool use_doorbell;
|
||||
bool use_bus_addr;
|
||||
dma_addr_t rb_dma_addr; /* only used when use_bus_addr = true */
|
||||
|
||||
struct amdgpu_bo *ring_obj;
|
||||
volatile uint32_t *ring;
|
||||
uint64_t gpu_addr;
|
||||
|
||||
uint64_t wptr_addr;
|
||||
volatile uint32_t *wptr_cpu;
|
||||
|
||||
uint64_t rptr_addr;
|
||||
volatile uint32_t *rptr_cpu;
|
||||
|
||||
bool enabled;
|
||||
unsigned rptr;
|
||||
atomic_t lock;
|
||||
};
|
||||
|
||||
/* provided by the ih block */
|
||||
struct amdgpu_ih_funcs {
|
||||
/* ring read/write ptr handling, called from interrupt context */
|
||||
u32 (*get_wptr)(struct amdgpu_device *adev);
|
||||
void (*decode_iv)(struct amdgpu_device *adev,
|
||||
u32 (*get_wptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
void (*decode_iv)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
void (*set_rptr)(struct amdgpu_device *adev);
|
||||
void (*set_rptr)(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
|
||||
};
|
||||
|
||||
#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
|
||||
#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
|
||||
#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
|
||||
#define amdgpu_ih_get_wptr(adev, ih) (adev)->irq.ih_funcs->get_wptr((adev), (ih))
|
||||
#define amdgpu_ih_decode_iv(adev, iv) \
|
||||
(adev)->irq.ih_funcs->decode_iv((adev), (ih), (iv))
|
||||
#define amdgpu_ih_set_rptr(adev, ih) (adev)->irq.ih_funcs->set_rptr((adev), (ih))
|
||||
|
||||
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
|
||||
unsigned ring_size, bool use_bus_addr);
|
||||
|
|
|
@ -148,6 +148,8 @@ static void amdgpu_irq_callback(struct amdgpu_device *adev,
|
|||
entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
|
||||
amdgpu_ih_decode_iv(adev, &entry);
|
||||
|
||||
trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
|
||||
|
||||
amdgpu_irq_dispatch(adev, &entry);
|
||||
}
|
||||
|
||||
|
@ -174,6 +176,36 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_handle_ih1 - kick of processing for IH1
|
||||
*
|
||||
* @work: work structure in struct amdgpu_irq
|
||||
*
|
||||
* Kick of processing IH ring 1.
|
||||
*/
|
||||
static void amdgpu_irq_handle_ih1(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
|
||||
irq.ih1_work);
|
||||
|
||||
amdgpu_ih_process(adev, &adev->irq.ih1, amdgpu_irq_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_irq_handle_ih2 - kick of processing for IH2
|
||||
*
|
||||
* @work: work structure in struct amdgpu_irq
|
||||
*
|
||||
* Kick of processing IH ring 2.
|
||||
*/
|
||||
static void amdgpu_irq_handle_ih2(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
|
||||
irq.ih2_work);
|
||||
|
||||
amdgpu_ih_process(adev, &adev->irq.ih2, amdgpu_irq_callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_msi_ok - check whether MSI functionality is enabled
|
||||
*
|
||||
|
@ -238,6 +270,9 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
amdgpu_hotplug_work_func);
|
||||
}
|
||||
|
||||
INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
|
||||
INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
|
||||
|
||||
adev->irq.installed = true;
|
||||
r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);
|
||||
if (r) {
|
||||
|
@ -367,8 +402,6 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
|||
bool handled = false;
|
||||
int r;
|
||||
|
||||
trace_amdgpu_iv(entry);
|
||||
|
||||
if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) {
|
||||
DRM_DEBUG("Invalid client_id in IV: %d\n", client_id);
|
||||
|
||||
|
|
|
@ -87,9 +87,11 @@ struct amdgpu_irq {
|
|||
/* status, etc. */
|
||||
bool msi_enabled; /* msi enabled */
|
||||
|
||||
/* interrupt ring */
|
||||
struct amdgpu_ih_ring ih;
|
||||
const struct amdgpu_ih_funcs *ih_funcs;
|
||||
/* interrupt rings */
|
||||
struct amdgpu_ih_ring ih, ih1, ih2;
|
||||
const struct amdgpu_ih_funcs *ih_funcs;
|
||||
struct work_struct ih1_work, ih2_work;
|
||||
struct amdgpu_irq_src self_irq;
|
||||
|
||||
/* gen irq stuff */
|
||||
struct irq_domain *domain; /* GPU irq controller domain */
|
||||
|
|
|
@ -626,11 +626,71 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie
|
||||
* DOC: ppfeatures
|
||||
*
|
||||
* The amdgpu driver provides a sysfs API for adjusting what powerplay
|
||||
* features to be enabled. The file ppfeatures is used for this. And
|
||||
* this is only available for Vega10 and later dGPUs.
|
||||
*
|
||||
* Reading back the file will show you the followings:
|
||||
* - Current ppfeature masks
|
||||
* - List of the all supported powerplay features with their naming,
|
||||
* bitmasks and enablement status('Y'/'N' means "enabled"/"disabled").
|
||||
*
|
||||
* To manually enable or disable a specific feature, just set or clear
|
||||
* the corresponding bit from original ppfeature masks and input the
|
||||
* new ppfeature masks.
|
||||
*/
|
||||
static ssize_t amdgpu_set_ppfeature_status(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint64_t featuremask;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou64(buf, 0, &featuremask);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("featuremask = 0x%llx\n", featuremask);
|
||||
|
||||
if (adev->powerplay.pp_funcs->set_ppfeature_status) {
|
||||
ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (adev->powerplay.pp_funcs->get_ppfeature_status)
|
||||
return amdgpu_dpm_get_ppfeature_status(adev, buf);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
|
||||
* pp_dpm_pcie
|
||||
*
|
||||
* The amdgpu driver provides a sysfs API for adjusting what power levels
|
||||
* are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk,
|
||||
* and pp_dpm_pcie are used for this.
|
||||
* pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for
|
||||
* this.
|
||||
*
|
||||
* pp_dpm_socclk and pp_dpm_dcefclk interfaces are only available for
|
||||
* Vega10 and later ASICs.
|
||||
* pp_dpm_fclk interface is only available for Vega20 and later ASICs.
|
||||
*
|
||||
* Reading back the files will show you the available power levels within
|
||||
* the power state and the clock information for those levels.
|
||||
|
@ -640,6 +700,8 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev,
|
|||
* Secondly,Enter a new value for each level by inputing a string that
|
||||
* contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
|
||||
* E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
|
||||
*
|
||||
* NOTE: change to the dcefclk max dpm level is not supported now
|
||||
*/
|
||||
|
||||
static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
|
||||
|
@ -750,6 +812,114 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "\n");
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "\n");
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
|
||||
if (adev->powerplay.pp_funcs->print_clock_levels)
|
||||
return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "\n");
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
int ret;
|
||||
uint32_t mask = 0;
|
||||
|
||||
ret = amdgpu_read_mask(buf, count, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adev->powerplay.pp_funcs->force_clock_level)
|
||||
ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
|
||||
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
@ -990,6 +1160,31 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev,
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: pcie_bw
|
||||
*
|
||||
* The amdgpu driver provides a sysfs API for estimating how much data
|
||||
* has been received and sent by the GPU in the last second through PCIe.
|
||||
* The file pcie_bw is used for this.
|
||||
* The Perf counters count the number of received and sent messages and return
|
||||
* those values, as well as the maximum payload size of a PCIe packet (mps).
|
||||
* Note that it is not possible to easily and quickly obtain the size of each
|
||||
* packet transmitted, so we output the max payload size (mps) to allow for
|
||||
* quick estimation of the PCIe bandwidth usage
|
||||
*/
|
||||
static ssize_t amdgpu_get_pcie_bw(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = ddev->dev_private;
|
||||
uint64_t count0, count1;
|
||||
|
||||
amdgpu_asic_get_pcie_usage(adev, &count0, &count1);
|
||||
return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n",
|
||||
count0, count1, pcie_get_mps(adev->pdev));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
|
||||
static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_dpm_forced_performance_level,
|
||||
|
@ -1008,6 +1203,15 @@ static DEVICE_ATTR(pp_dpm_sclk, S_IRUGO | S_IWUSR,
|
|||
static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_pp_dpm_mclk,
|
||||
amdgpu_set_pp_dpm_mclk);
|
||||
static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_pp_dpm_socclk,
|
||||
amdgpu_set_pp_dpm_socclk);
|
||||
static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_pp_dpm_fclk,
|
||||
amdgpu_set_pp_dpm_fclk);
|
||||
static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_pp_dpm_dcefclk,
|
||||
amdgpu_set_pp_dpm_dcefclk);
|
||||
static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_pp_dpm_pcie,
|
||||
amdgpu_set_pp_dpm_pcie);
|
||||
|
@ -1025,6 +1229,10 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR,
|
|||
amdgpu_set_pp_od_clk_voltage);
|
||||
static DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
|
||||
amdgpu_get_busy_percent, NULL);
|
||||
static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL);
|
||||
static DEVICE_ATTR(ppfeatures, S_IRUGO | S_IWUSR,
|
||||
amdgpu_get_ppfeature_status,
|
||||
amdgpu_set_ppfeature_status);
|
||||
|
||||
static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -1516,6 +1724,75 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_hwmon_show_sclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
struct drm_device *ddev = adev->ddev;
|
||||
uint32_t sclk;
|
||||
int r, size = sizeof(sclk);
|
||||
|
||||
/* Can't get voltage when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
/* sanity check PP is enabled */
|
||||
if (!(adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->read_sensor))
|
||||
return -EINVAL;
|
||||
|
||||
/* get the sclk */
|
||||
r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK,
|
||||
(void *)&sclk, &size);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000);
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "sclk\n");
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_hwmon_show_mclk(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct amdgpu_device *adev = dev_get_drvdata(dev);
|
||||
struct drm_device *ddev = adev->ddev;
|
||||
uint32_t mclk;
|
||||
int r, size = sizeof(mclk);
|
||||
|
||||
/* Can't get voltage when the card is off */
|
||||
if ((adev->flags & AMD_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
/* sanity check PP is enabled */
|
||||
if (!(adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->read_sensor))
|
||||
return -EINVAL;
|
||||
|
||||
/* get the sclk */
|
||||
r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK,
|
||||
(void *)&mclk, &size);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000);
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "mclk\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: hwmon
|
||||
|
@ -1532,6 +1809,10 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
|
|||
*
|
||||
* - GPU fan
|
||||
*
|
||||
* - GPU gfx/compute engine clock
|
||||
*
|
||||
* - GPU memory clock (dGPU only)
|
||||
*
|
||||
* hwmon interfaces for GPU temperature:
|
||||
*
|
||||
* - temp1_input: the on die GPU temperature in millidegrees Celsius
|
||||
|
@ -1576,6 +1857,12 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
|
|||
*
|
||||
* - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable
|
||||
*
|
||||
* hwmon interfaces for GPU clocks:
|
||||
*
|
||||
* - freq1_input: the gfx/compute clock in hertz
|
||||
*
|
||||
* - freq2_input: the memory clock in hertz
|
||||
*
|
||||
* You can use hwmon tools like sensors to view this information on your system.
|
||||
*
|
||||
*/
|
||||
|
@ -1600,6 +1887,10 @@ static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg,
|
|||
static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0);
|
||||
static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label, NULL, 0);
|
||||
|
||||
static struct attribute *hwmon_attributes[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
|
@ -1622,6 +1913,10 @@ static struct attribute *hwmon_attributes[] = {
|
|||
&sensor_dev_attr_power1_cap_max.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_cap_min.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_cap.dev_attr.attr,
|
||||
&sensor_dev_attr_freq1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_freq1_label.dev_attr.attr,
|
||||
&sensor_dev_attr_freq2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_freq2_label.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1686,7 +1981,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
|
|||
effective_mode &= ~S_IWUSR;
|
||||
|
||||
if ((adev->flags & AMD_IS_APU) &&
|
||||
(attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
|
||||
(attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
|
||||
attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
|
||||
return 0;
|
||||
|
@ -1712,6 +2008,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
|
|||
attr == &sensor_dev_attr_in1_label.dev_attr.attr))
|
||||
return 0;
|
||||
|
||||
/* no mclk on APUs */
|
||||
if ((adev->flags & AMD_IS_APU) &&
|
||||
(attr == &sensor_dev_attr_freq2_input.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_freq2_label.dev_attr.attr))
|
||||
return 0;
|
||||
|
||||
return effective_mode;
|
||||
}
|
||||
|
||||
|
@ -2008,6 +2310,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
|
|||
|
||||
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
|
||||
int ret;
|
||||
|
||||
if (adev->pm.sysfs_initialized)
|
||||
|
@ -2069,6 +2372,25 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
|
|||
DRM_ERROR("failed to create device file pp_dpm_mclk\n");
|
||||
return ret;
|
||||
}
|
||||
if (adev->asic_type >= CHIP_VEGA10) {
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_socclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_socclk\n");
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (adev->asic_type >= CHIP_VEGA20) {
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_fclk);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_fclk\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pp_dpm_pcie\n");
|
||||
|
@ -2091,12 +2413,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
|
|||
"pp_power_profile_mode\n");
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(adev->dev,
|
||||
&dev_attr_pp_od_clk_voltage);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file "
|
||||
"pp_od_clk_voltage\n");
|
||||
return ret;
|
||||
if (hwmgr->od_enabled) {
|
||||
ret = device_create_file(adev->dev,
|
||||
&dev_attr_pp_od_clk_voltage);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file "
|
||||
"pp_od_clk_voltage\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = device_create_file(adev->dev,
|
||||
&dev_attr_gpu_busy_percent);
|
||||
|
@ -2105,12 +2429,31 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
|
|||
"gpu_busy_level\n");
|
||||
return ret;
|
||||
}
|
||||
/* PCIe Perf counters won't work on APU nodes */
|
||||
if (!(adev->flags & AMD_IS_APU)) {
|
||||
ret = device_create_file(adev->dev, &dev_attr_pcie_bw);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file pcie_bw\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = amdgpu_debugfs_pm_init(adev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to register debugfs file for dpm!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((adev->asic_type >= CHIP_VEGA10) &&
|
||||
!(adev->flags & AMD_IS_APU)) {
|
||||
ret = device_create_file(adev->dev,
|
||||
&dev_attr_ppfeatures);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create device file "
|
||||
"ppfeatures\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
adev->pm.sysfs_initialized = true;
|
||||
|
||||
return 0;
|
||||
|
@ -2118,6 +2461,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
|
|||
|
||||
void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
|
||||
|
||||
if (adev->pm.dpm_enabled == 0)
|
||||
return;
|
||||
|
||||
|
@ -2133,14 +2478,26 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
|
|||
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk);
|
||||
if (adev->asic_type >= CHIP_VEGA10) {
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
|
||||
}
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
|
||||
if (adev->asic_type >= CHIP_VEGA20)
|
||||
device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
|
||||
device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
|
||||
device_remove_file(adev->dev,
|
||||
&dev_attr_pp_power_profile_mode);
|
||||
device_remove_file(adev->dev,
|
||||
&dev_attr_pp_od_clk_voltage);
|
||||
if (hwmgr->od_enabled)
|
||||
device_remove_file(adev->dev,
|
||||
&dev_attr_pp_od_clk_voltage);
|
||||
device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
|
||||
if (!(adev->flags & AMD_IS_APU))
|
||||
device_remove_file(adev->dev, &dev_attr_pcie_bw);
|
||||
if ((adev->asic_type >= CHIP_VEGA10) &&
|
||||
!(adev->flags & AMD_IS_APU))
|
||||
device_remove_file(adev->dev, &dev_attr_ppfeatures);
|
||||
}
|
||||
|
||||
void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
|
||||
|
|
|
@ -67,9 +67,6 @@ static int psp_sw_init(void *handle)
|
|||
|
||||
psp->adev = adev;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
ret = psp_init_microcode(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to load psp firmware!\n");
|
||||
|
@ -83,9 +80,6 @@ static int psp_sw_fini(void *handle)
|
|||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
release_firmware(adev->psp.sos_fw);
|
||||
adev->psp.sos_fw = NULL;
|
||||
release_firmware(adev->psp.asd_fw);
|
||||
|
@ -140,13 +134,24 @@ psp_cmd_submit_buf(struct psp_context *psp,
|
|||
while (*((unsigned int *)psp->fence_buf) != index)
|
||||
msleep(1);
|
||||
|
||||
/* the status field must be 0 after FW is loaded */
|
||||
if (ucode && psp->cmd_buf_mem->resp.status) {
|
||||
DRM_ERROR("failed loading with status (%d) and ucode id (%d)\n",
|
||||
psp->cmd_buf_mem->resp.status, ucode->ucode_id);
|
||||
return -EINVAL;
|
||||
/* In some cases, psp response status is not 0 even there is no
|
||||
* problem while the command is submitted. Some version of PSP FW
|
||||
* doesn't write 0 to that field.
|
||||
* So here we would like to only print a warning instead of an error
|
||||
* during psp initialization to avoid breaking hw_init and it doesn't
|
||||
* return -EINVAL.
|
||||
*/
|
||||
if (psp->cmd_buf_mem->resp.status) {
|
||||
if (ucode)
|
||||
DRM_WARN("failed to load ucode id (%d) ",
|
||||
ucode->ucode_id);
|
||||
DRM_WARN("psp command failed and response status is (%d)\n",
|
||||
psp->cmd_buf_mem->resp.status);
|
||||
}
|
||||
|
||||
/* get xGMI session id from response buffer */
|
||||
cmd->resp.session_id = psp->cmd_buf_mem->resp.session_id;
|
||||
|
||||
if (ucode) {
|
||||
ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
|
||||
ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
|
||||
|
@ -495,6 +500,98 @@ static int psp_hw_start(struct psp_context *psp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
|
||||
enum psp_gfx_fw_type *type)
|
||||
{
|
||||
switch (ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*type = GFX_FW_TYPE_SDMA0;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SDMA1:
|
||||
*type = GFX_FW_TYPE_SDMA1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_CE:
|
||||
*type = GFX_FW_TYPE_CP_CE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_PFP:
|
||||
*type = GFX_FW_TYPE_CP_PFP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_ME:
|
||||
*type = GFX_FW_TYPE_CP_ME;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME2;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
*type = GFX_FW_TYPE_RLC_G;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SMC:
|
||||
*type = GFX_FW_TYPE_SMU;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD:
|
||||
*type = GFX_FW_TYPE_UVD;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD1:
|
||||
*type = GFX_FW_TYPE_UVD1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCE:
|
||||
*type = GFX_FW_TYPE_VCE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCN:
|
||||
*type = GFX_FW_TYPE_VCN;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_DMCU_ERAM:
|
||||
*type = GFX_FW_TYPE_DMCU_ERAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_DMCU_INTV:
|
||||
*type = GFX_FW_TYPE_DMCU_ISR;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
|
||||
struct psp_gfx_cmd_resp *cmd)
|
||||
{
|
||||
int ret;
|
||||
uint64_t fw_mem_mc_addr = ucode->mc_addr;
|
||||
|
||||
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
|
||||
|
||||
ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
|
||||
if (ret)
|
||||
DRM_ERROR("Unknown firmware type\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_np_fw_load(struct psp_context *psp)
|
||||
{
|
||||
int i, ret;
|
||||
|
@ -516,7 +613,7 @@ static int psp_np_fw_load(struct psp_context *psp)
|
|||
/*skip ucode loading in SRIOV VF */
|
||||
continue;
|
||||
|
||||
ret = psp_prep_cmd_buf(ucode, psp->cmd);
|
||||
ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -541,7 +638,7 @@ static int psp_load_fw(struct amdgpu_device *adev)
|
|||
struct psp_context *psp = &adev->psp;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) {
|
||||
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
|
||||
psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */
|
||||
goto skip_memalloc;
|
||||
}
|
||||
|
||||
|
@ -618,10 +715,6 @@ static int psp_hw_init(void *handle)
|
|||
int ret;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->firmware.mutex);
|
||||
/*
|
||||
* This sequence is just used on hw_init only once, no need on
|
||||
|
@ -651,9 +744,6 @@ static int psp_hw_fini(void *handle)
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct psp_context *psp = &adev->psp;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1 &&
|
||||
psp->xgmi_context.initialized == 1)
|
||||
psp_xgmi_terminate(psp);
|
||||
|
@ -682,9 +772,6 @@ static int psp_suspend(void *handle)
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct psp_context *psp = &adev->psp;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
if (adev->gmc.xgmi.num_physical_nodes > 1 &&
|
||||
psp->xgmi_context.initialized == 1) {
|
||||
ret = psp_xgmi_terminate(psp);
|
||||
|
@ -709,9 +796,6 @@ static int psp_resume(void *handle)
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
struct psp_context *psp = &adev->psp;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
|
||||
return 0;
|
||||
|
||||
DRM_INFO("PSP is resuming...\n");
|
||||
|
||||
mutex_lock(&adev->firmware.mutex);
|
||||
|
@ -747,11 +831,6 @@ static bool psp_check_fw_loading_status(struct amdgpu_device *adev,
|
|||
{
|
||||
struct amdgpu_firmware_info *ucode = NULL;
|
||||
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
|
||||
DRM_INFO("firmware is not loaded by PSP\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!adev->firmware.fw_size)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -65,8 +65,6 @@ struct psp_funcs
|
|||
int (*init_microcode)(struct psp_context *psp);
|
||||
int (*bootloader_load_sysdrv)(struct psp_context *psp);
|
||||
int (*bootloader_load_sos)(struct psp_context *psp);
|
||||
int (*prep_cmd_buf)(struct amdgpu_firmware_info *ucode,
|
||||
struct psp_gfx_cmd_resp *cmd);
|
||||
int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
|
||||
int (*ring_create)(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type);
|
||||
|
@ -176,7 +174,6 @@ struct psp_xgmi_topology_info {
|
|||
struct psp_xgmi_node_info nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES];
|
||||
};
|
||||
|
||||
#define psp_prep_cmd_buf(ucode, type) (psp)->funcs->prep_cmd_buf((ucode), (type))
|
||||
#define psp_ring_init(psp, type) (psp)->funcs->ring_init((psp), (type))
|
||||
#define psp_ring_create(psp, type) (psp)->funcs->ring_create((psp), (type))
|
||||
#define psp_ring_stop(psp, type) (psp)->funcs->ring_stop((psp), (type))
|
||||
|
|
|
@ -131,7 +131,7 @@ struct amdgpu_ring_funcs {
|
|||
void (*emit_ib)(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch);
|
||||
uint32_t flags);
|
||||
void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
|
||||
uint64_t seq, unsigned flags);
|
||||
void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
|
||||
|
@ -229,7 +229,7 @@ struct amdgpu_ring {
|
|||
#define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r))
|
||||
#define amdgpu_ring_get_wptr(r) (r)->funcs->get_wptr((r))
|
||||
#define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r))
|
||||
#define amdgpu_ring_emit_ib(r, job, ib, c) ((r)->funcs->emit_ib((r), (job), (ib), (c)))
|
||||
#define amdgpu_ring_emit_ib(r, job, ib, flags) ((r)->funcs->emit_ib((r), (job), (ib), (flags)))
|
||||
#define amdgpu_ring_emit_pipeline_sync(r) (r)->funcs->emit_pipeline_sync((r))
|
||||
#define amdgpu_ring_emit_vm_flush(r, vmid, addr) (r)->funcs->emit_vm_flush((r), (vmid), (addr))
|
||||
#define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags))
|
||||
|
|
|
@ -76,9 +76,10 @@ TRACE_EVENT(amdgpu_mm_wreg,
|
|||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_iv,
|
||||
TP_PROTO(struct amdgpu_iv_entry *iv),
|
||||
TP_ARGS(iv),
|
||||
TP_PROTO(unsigned ih, struct amdgpu_iv_entry *iv),
|
||||
TP_ARGS(ih, iv),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned, ih)
|
||||
__field(unsigned, client_id)
|
||||
__field(unsigned, src_id)
|
||||
__field(unsigned, ring_id)
|
||||
|
@ -90,6 +91,7 @@ TRACE_EVENT(amdgpu_iv,
|
|||
__array(unsigned, src_data, 4)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ih = ih;
|
||||
__entry->client_id = iv->client_id;
|
||||
__entry->src_id = iv->src_id;
|
||||
__entry->ring_id = iv->ring_id;
|
||||
|
@ -103,8 +105,9 @@ TRACE_EVENT(amdgpu_iv,
|
|||
__entry->src_data[2] = iv->src_data[2];
|
||||
__entry->src_data[3] = iv->src_data[3];
|
||||
),
|
||||
TP_printk("client_id:%u src_id:%u ring:%u vmid:%u timestamp: %llu pasid:%u src_data: %08x %08x %08x %08x",
|
||||
__entry->client_id, __entry->src_id,
|
||||
TP_printk("ih:%u client_id:%u src_id:%u ring:%u vmid:%u "
|
||||
"timestamp: %llu pasid:%u src_data: %08x %08x %08x %08x",
|
||||
__entry->ih, __entry->client_id, __entry->src_id,
|
||||
__entry->ring_id, __entry->vmid,
|
||||
__entry->timestamp, __entry->pasid,
|
||||
__entry->src_data[0], __entry->src_data[1],
|
||||
|
|
|
@ -1546,7 +1546,8 @@ static struct ttm_bo_driver amdgpu_bo_driver = {
|
|||
.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
|
||||
.io_mem_free = &amdgpu_ttm_io_mem_free,
|
||||
.io_mem_pfn = amdgpu_ttm_io_mem_pfn,
|
||||
.access_memory = &amdgpu_ttm_access_memory
|
||||
.access_memory = &amdgpu_ttm_access_memory,
|
||||
.del_from_lru_notify = &amdgpu_vm_del_from_lru_notify
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1035,7 +1035,7 @@ int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx)
|
|||
void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
amdgpu_ring_write(ring, VCE_CMD_IB);
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
|
|
@ -66,7 +66,7 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
|
|||
int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
|
||||
int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx);
|
||||
void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib, bool ctx_switch);
|
||||
struct amdgpu_ib *ib, uint32_t flags);
|
||||
void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
|
||||
unsigned flags);
|
||||
int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
|
||||
|
|
|
@ -623,6 +623,28 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
|
|||
list_add(&entry->tv.head, validated);
|
||||
}
|
||||
|
||||
void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct amdgpu_bo *abo;
|
||||
struct amdgpu_vm_bo_base *bo_base;
|
||||
|
||||
if (!amdgpu_bo_is_amdgpu_bo(bo))
|
||||
return;
|
||||
|
||||
if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)
|
||||
return;
|
||||
|
||||
abo = ttm_to_amdgpu_bo(bo);
|
||||
if (!abo->parent)
|
||||
return;
|
||||
for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) {
|
||||
struct amdgpu_vm *vm = bo_base->vm;
|
||||
|
||||
if (abo->tbo.resv == vm->root.base.bo->tbo.resv)
|
||||
vm->bulk_moveable = false;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* amdgpu_vm_move_to_lru_tail - move all BOs to the end of LRU
|
||||
*
|
||||
|
@ -799,9 +821,16 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
|
|||
addr += ats_entries * 8;
|
||||
}
|
||||
|
||||
if (entries)
|
||||
if (entries) {
|
||||
uint64_t value = 0;
|
||||
|
||||
/* Workaround for fault priority problem on GMC9 */
|
||||
if (level == AMDGPU_VM_PTB && adev->asic_type >= CHIP_VEGA10)
|
||||
value = AMDGPU_PTE_EXECUTABLE;
|
||||
|
||||
amdgpu_vm_set_pte_pde(adev, &job->ibs[0], addr, 0,
|
||||
entries, 0, 0);
|
||||
entries, 0, value);
|
||||
}
|
||||
|
||||
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
|
||||
|
||||
|
@ -847,9 +876,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
bp->size = amdgpu_vm_bo_size(adev, level);
|
||||
bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
|
||||
bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
|
||||
if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 &&
|
||||
adev->flags & AMD_IS_APU)
|
||||
bp->domain |= AMDGPU_GEM_DOMAIN_GTT;
|
||||
bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
|
||||
bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
|
@ -1506,20 +1532,27 @@ int amdgpu_vm_update_directories(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_update_huge - figure out parameters for PTE updates
|
||||
* amdgpu_vm_update_flags - figure out flags for PTE updates
|
||||
*
|
||||
* Make sure to set the right flags for the PTEs at the desired level.
|
||||
*/
|
||||
static void amdgpu_vm_update_huge(struct amdgpu_pte_update_params *params,
|
||||
struct amdgpu_bo *bo, unsigned level,
|
||||
uint64_t pe, uint64_t addr,
|
||||
unsigned count, uint32_t incr,
|
||||
uint64_t flags)
|
||||
static void amdgpu_vm_update_flags(struct amdgpu_pte_update_params *params,
|
||||
struct amdgpu_bo *bo, unsigned level,
|
||||
uint64_t pe, uint64_t addr,
|
||||
unsigned count, uint32_t incr,
|
||||
uint64_t flags)
|
||||
|
||||
{
|
||||
if (level != AMDGPU_VM_PTB) {
|
||||
flags |= AMDGPU_PDE_PTE;
|
||||
amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags);
|
||||
|
||||
} else if (params->adev->asic_type >= CHIP_VEGA10 &&
|
||||
!(flags & AMDGPU_PTE_VALID) &&
|
||||
!(flags & AMDGPU_PTE_PRT)) {
|
||||
|
||||
/* Workaround for fault priority problem on GMC9 */
|
||||
flags |= AMDGPU_PTE_EXECUTABLE;
|
||||
}
|
||||
|
||||
amdgpu_vm_update_func(params, bo, pe, addr, count, incr, flags);
|
||||
|
@ -1676,9 +1709,9 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
|
|||
uint64_t upd_end = min(entry_end, frag_end);
|
||||
unsigned nptes = (upd_end - frag_start) >> shift;
|
||||
|
||||
amdgpu_vm_update_huge(params, pt, cursor.level,
|
||||
pe_start, dst, nptes, incr,
|
||||
flags | AMDGPU_PTE_FRAG(frag));
|
||||
amdgpu_vm_update_flags(params, pt, cursor.level,
|
||||
pe_start, dst, nptes, incr,
|
||||
flags | AMDGPU_PTE_FRAG(frag));
|
||||
|
||||
pe_start += nptes * 8;
|
||||
dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;
|
||||
|
@ -3006,7 +3039,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
}
|
||||
DRM_DEBUG_DRIVER("VM update mode is %s\n",
|
||||
vm->use_cpu_for_update ? "CPU" : "SDMA");
|
||||
WARN_ONCE((vm->use_cpu_for_update & !amdgpu_gmc_vram_full_visible(&adev->gmc)),
|
||||
WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
|
||||
"CPU update of VM recommended only for large BAR system\n");
|
||||
vm->last_update = NULL;
|
||||
|
||||
|
@ -3136,7 +3169,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
|
|||
vm->pte_support_ats = pte_support_ats;
|
||||
DRM_DEBUG_DRIVER("VM update mode is %s\n",
|
||||
vm->use_cpu_for_update ? "CPU" : "SDMA");
|
||||
WARN_ONCE((vm->use_cpu_for_update & !amdgpu_gmc_vram_full_visible(&adev->gmc)),
|
||||
WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
|
||||
"CPU update of VM recommended only for large BAR system\n");
|
||||
|
||||
if (vm->pasid) {
|
||||
|
|
|
@ -363,4 +363,6 @@ int amdgpu_vm_add_fault(struct amdgpu_retryfault_hashtable *fault_hash, u64 key)
|
|||
|
||||
void amdgpu_vm_clear_fault(struct amdgpu_retryfault_hashtable *fault_hash, u64 key);
|
||||
|
||||
void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,26 +40,40 @@ void *amdgpu_xgmi_hive_try_lock(struct amdgpu_hive_info *hive)
|
|||
return &hive->device_list;
|
||||
}
|
||||
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_hive_info *tmp;
|
||||
|
||||
if (!adev->gmc.xgmi.hive_id)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&xgmi_mutex);
|
||||
|
||||
for (i = 0 ; i < hive_count; ++i) {
|
||||
tmp = &xgmi_hives[i];
|
||||
if (tmp->hive_id == adev->gmc.xgmi.hive_id)
|
||||
if (tmp->hive_id == adev->gmc.xgmi.hive_id) {
|
||||
if (lock)
|
||||
mutex_lock(&tmp->hive_lock);
|
||||
mutex_unlock(&xgmi_mutex);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
if (i >= AMDGPU_MAX_XGMI_HIVE)
|
||||
if (i >= AMDGPU_MAX_XGMI_HIVE) {
|
||||
mutex_unlock(&xgmi_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize new hive if not exist */
|
||||
tmp = &xgmi_hives[hive_count++];
|
||||
tmp->hive_id = adev->gmc.xgmi.hive_id;
|
||||
INIT_LIST_HEAD(&tmp->device_list);
|
||||
mutex_init(&tmp->hive_lock);
|
||||
mutex_init(&tmp->reset_lock);
|
||||
if (lock)
|
||||
mutex_lock(&tmp->hive_lock);
|
||||
|
||||
mutex_unlock(&xgmi_mutex);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
@ -111,10 +125,14 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&xgmi_mutex);
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
if (!hive)
|
||||
hive = amdgpu_get_xgmi_hive(adev, 1);
|
||||
if (!hive) {
|
||||
ret = -EINVAL;
|
||||
dev_err(adev->dev,
|
||||
"XGMI: node 0x%llx, can not matech hive 0x%llx in the hive list.\n",
|
||||
adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hive_topology = &hive->topology_info;
|
||||
|
||||
|
@ -142,8 +160,8 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
|
|||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
exit:
|
||||
mutex_unlock(&xgmi_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -154,15 +172,14 @@ void amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
|
|||
if (!adev->gmc.xgmi.supported)
|
||||
return;
|
||||
|
||||
mutex_lock(&xgmi_mutex);
|
||||
|
||||
hive = amdgpu_get_xgmi_hive(adev);
|
||||
hive = amdgpu_get_xgmi_hive(adev, 1);
|
||||
if (!hive)
|
||||
goto exit;
|
||||
return;
|
||||
|
||||
if (!(hive->number_devices--))
|
||||
if (!(hive->number_devices--)) {
|
||||
mutex_destroy(&hive->hive_lock);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&xgmi_mutex);
|
||||
mutex_destroy(&hive->reset_lock);
|
||||
} else {
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,11 @@ struct amdgpu_hive_info {
|
|||
struct list_head device_list;
|
||||
struct psp_xgmi_topology_info topology_info;
|
||||
int number_devices;
|
||||
struct mutex hive_lock;
|
||||
struct mutex hive_lock,
|
||||
reset_lock;
|
||||
};
|
||||
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev);
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock);
|
||||
int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_add_device(struct amdgpu_device *adev);
|
||||
void amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,349 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 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 __CI_DPM_H__
|
||||
#define __CI_DPM_H__
|
||||
|
||||
#include "amdgpu_atombios.h"
|
||||
#include "ppsmc.h"
|
||||
|
||||
#define SMU__NUM_SCLK_DPM_STATE 8
|
||||
#define SMU__NUM_MCLK_DPM_LEVELS 6
|
||||
#define SMU__NUM_LCLK_DPM_LEVELS 8
|
||||
#define SMU__NUM_PCIE_DPM_LEVELS 8
|
||||
#include "smu7_discrete.h"
|
||||
|
||||
#define CISLANDS_MAX_HARDWARE_POWERLEVELS 2
|
||||
|
||||
#define CISLANDS_UNUSED_GPIO_PIN 0x7F
|
||||
|
||||
struct ci_pl {
|
||||
u32 mclk;
|
||||
u32 sclk;
|
||||
enum amdgpu_pcie_gen pcie_gen;
|
||||
u16 pcie_lane;
|
||||
};
|
||||
|
||||
struct ci_ps {
|
||||
u16 performance_level_count;
|
||||
bool dc_compatible;
|
||||
u32 sclk_t;
|
||||
struct ci_pl performance_levels[CISLANDS_MAX_HARDWARE_POWERLEVELS];
|
||||
};
|
||||
|
||||
struct ci_dpm_level {
|
||||
bool enabled;
|
||||
u32 value;
|
||||
u32 param1;
|
||||
};
|
||||
|
||||
#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5
|
||||
#define MAX_REGULAR_DPM_NUMBER 8
|
||||
#define CISLAND_MINIMUM_ENGINE_CLOCK 800
|
||||
|
||||
struct ci_single_dpm_table {
|
||||
u32 count;
|
||||
struct ci_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
|
||||
};
|
||||
|
||||
struct ci_dpm_table {
|
||||
struct ci_single_dpm_table sclk_table;
|
||||
struct ci_single_dpm_table mclk_table;
|
||||
struct ci_single_dpm_table pcie_speed_table;
|
||||
struct ci_single_dpm_table vddc_table;
|
||||
struct ci_single_dpm_table vddci_table;
|
||||
struct ci_single_dpm_table mvdd_table;
|
||||
};
|
||||
|
||||
struct ci_mc_reg_entry {
|
||||
u32 mclk_max;
|
||||
u32 mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
struct ci_mc_reg_table {
|
||||
u8 last;
|
||||
u8 num_entries;
|
||||
u16 valid_flag;
|
||||
struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
|
||||
SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
|
||||
};
|
||||
|
||||
struct ci_ulv_parm
|
||||
{
|
||||
bool supported;
|
||||
u32 cg_ulv_parameter;
|
||||
u32 volt_change_delay;
|
||||
struct ci_pl pl;
|
||||
};
|
||||
|
||||
#define CISLANDS_MAX_LEAKAGE_COUNT 8
|
||||
|
||||
struct ci_leakage_voltage {
|
||||
u16 count;
|
||||
u16 leakage_id[CISLANDS_MAX_LEAKAGE_COUNT];
|
||||
u16 actual_voltage[CISLANDS_MAX_LEAKAGE_COUNT];
|
||||
};
|
||||
|
||||
struct ci_dpm_level_enable_mask {
|
||||
u32 uvd_dpm_enable_mask;
|
||||
u32 vce_dpm_enable_mask;
|
||||
u32 acp_dpm_enable_mask;
|
||||
u32 samu_dpm_enable_mask;
|
||||
u32 sclk_dpm_enable_mask;
|
||||
u32 mclk_dpm_enable_mask;
|
||||
u32 pcie_dpm_enable_mask;
|
||||
};
|
||||
|
||||
struct ci_vbios_boot_state
|
||||
{
|
||||
u16 mvdd_bootup_value;
|
||||
u16 vddc_bootup_value;
|
||||
u16 vddci_bootup_value;
|
||||
u32 sclk_bootup_value;
|
||||
u32 mclk_bootup_value;
|
||||
u16 pcie_gen_bootup_value;
|
||||
u16 pcie_lane_bootup_value;
|
||||
};
|
||||
|
||||
struct ci_clock_registers {
|
||||
u32 cg_spll_func_cntl;
|
||||
u32 cg_spll_func_cntl_2;
|
||||
u32 cg_spll_func_cntl_3;
|
||||
u32 cg_spll_func_cntl_4;
|
||||
u32 cg_spll_spread_spectrum;
|
||||
u32 cg_spll_spread_spectrum_2;
|
||||
u32 dll_cntl;
|
||||
u32 mclk_pwrmgt_cntl;
|
||||
u32 mpll_ad_func_cntl;
|
||||
u32 mpll_dq_func_cntl;
|
||||
u32 mpll_func_cntl;
|
||||
u32 mpll_func_cntl_1;
|
||||
u32 mpll_func_cntl_2;
|
||||
u32 mpll_ss1;
|
||||
u32 mpll_ss2;
|
||||
};
|
||||
|
||||
struct ci_thermal_temperature_setting {
|
||||
s32 temperature_low;
|
||||
s32 temperature_high;
|
||||
s32 temperature_shutdown;
|
||||
};
|
||||
|
||||
struct ci_pcie_perf_range {
|
||||
u16 max;
|
||||
u16 min;
|
||||
};
|
||||
|
||||
enum ci_pt_config_reg_type {
|
||||
CISLANDS_CONFIGREG_MMR = 0,
|
||||
CISLANDS_CONFIGREG_SMC_IND,
|
||||
CISLANDS_CONFIGREG_DIDT_IND,
|
||||
CISLANDS_CONFIGREG_CACHE,
|
||||
CISLANDS_CONFIGREG_MAX
|
||||
};
|
||||
|
||||
#define POWERCONTAINMENT_FEATURE_BAPM 0x00000001
|
||||
#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002
|
||||
#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004
|
||||
|
||||
struct ci_pt_config_reg {
|
||||
u32 offset;
|
||||
u32 mask;
|
||||
u32 shift;
|
||||
u32 value;
|
||||
enum ci_pt_config_reg_type type;
|
||||
};
|
||||
|
||||
struct ci_pt_defaults {
|
||||
u8 svi_load_line_en;
|
||||
u8 svi_load_line_vddc;
|
||||
u8 tdc_vddc_throttle_release_limit_perc;
|
||||
u8 tdc_mawt;
|
||||
u8 tdc_waterfall_ctl;
|
||||
u8 dte_ambient_temp_base;
|
||||
u32 display_cac;
|
||||
u32 bapm_temp_gradient;
|
||||
u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
|
||||
u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
|
||||
};
|
||||
|
||||
#define DPMTABLE_OD_UPDATE_SCLK 0x00000001
|
||||
#define DPMTABLE_OD_UPDATE_MCLK 0x00000002
|
||||
#define DPMTABLE_UPDATE_SCLK 0x00000004
|
||||
#define DPMTABLE_UPDATE_MCLK 0x00000008
|
||||
|
||||
struct ci_power_info {
|
||||
struct ci_dpm_table dpm_table;
|
||||
struct ci_dpm_table golden_dpm_table;
|
||||
u32 voltage_control;
|
||||
u32 mvdd_control;
|
||||
u32 vddci_control;
|
||||
u32 active_auto_throttle_sources;
|
||||
struct ci_clock_registers clock_registers;
|
||||
u16 acpi_vddc;
|
||||
u16 acpi_vddci;
|
||||
enum amdgpu_pcie_gen force_pcie_gen;
|
||||
enum amdgpu_pcie_gen acpi_pcie_gen;
|
||||
struct ci_leakage_voltage vddc_leakage;
|
||||
struct ci_leakage_voltage vddci_leakage;
|
||||
u16 max_vddc_in_pp_table;
|
||||
u16 min_vddc_in_pp_table;
|
||||
u16 max_vddci_in_pp_table;
|
||||
u16 min_vddci_in_pp_table;
|
||||
u32 mclk_strobe_mode_threshold;
|
||||
u32 mclk_stutter_mode_threshold;
|
||||
u32 mclk_edc_enable_threshold;
|
||||
u32 mclk_edc_wr_enable_threshold;
|
||||
struct ci_vbios_boot_state vbios_boot_state;
|
||||
/* smc offsets */
|
||||
u32 sram_end;
|
||||
u32 dpm_table_start;
|
||||
u32 soft_regs_start;
|
||||
u32 mc_reg_table_start;
|
||||
u32 fan_table_start;
|
||||
u32 arb_table_start;
|
||||
/* smc tables */
|
||||
SMU7_Discrete_DpmTable smc_state_table;
|
||||
SMU7_Discrete_MCRegisters smc_mc_reg_table;
|
||||
SMU7_Discrete_PmFuses smc_powertune_table;
|
||||
/* other stuff */
|
||||
struct ci_mc_reg_table mc_reg_table;
|
||||
struct atom_voltage_table vddc_voltage_table;
|
||||
struct atom_voltage_table vddci_voltage_table;
|
||||
struct atom_voltage_table mvdd_voltage_table;
|
||||
struct ci_ulv_parm ulv;
|
||||
u32 power_containment_features;
|
||||
const struct ci_pt_defaults *powertune_defaults;
|
||||
u32 dte_tj_offset;
|
||||
bool vddc_phase_shed_control;
|
||||
struct ci_thermal_temperature_setting thermal_temp_setting;
|
||||
struct ci_dpm_level_enable_mask dpm_level_enable_mask;
|
||||
u32 need_update_smu7_dpm_table;
|
||||
u32 sclk_dpm_key_disabled;
|
||||
u32 mclk_dpm_key_disabled;
|
||||
u32 pcie_dpm_key_disabled;
|
||||
u32 thermal_sclk_dpm_enabled;
|
||||
struct ci_pcie_perf_range pcie_gen_performance;
|
||||
struct ci_pcie_perf_range pcie_lane_performance;
|
||||
struct ci_pcie_perf_range pcie_gen_powersaving;
|
||||
struct ci_pcie_perf_range pcie_lane_powersaving;
|
||||
u32 activity_target[SMU7_MAX_LEVELS_GRAPHICS];
|
||||
u32 mclk_activity_target;
|
||||
u32 low_sclk_interrupt_t;
|
||||
u32 last_mclk_dpm_enable_mask;
|
||||
u32 sys_pcie_mask;
|
||||
/* caps */
|
||||
bool caps_power_containment;
|
||||
bool caps_cac;
|
||||
bool caps_sq_ramping;
|
||||
bool caps_db_ramping;
|
||||
bool caps_td_ramping;
|
||||
bool caps_tcp_ramping;
|
||||
bool caps_fps;
|
||||
bool caps_sclk_ds;
|
||||
bool caps_sclk_ss_support;
|
||||
bool caps_mclk_ss_support;
|
||||
bool caps_uvd_dpm;
|
||||
bool caps_vce_dpm;
|
||||
bool caps_samu_dpm;
|
||||
bool caps_acp_dpm;
|
||||
bool caps_automatic_dc_transition;
|
||||
bool caps_sclk_throttle_low_notification;
|
||||
bool caps_dynamic_ac_timing;
|
||||
bool caps_od_fuzzy_fan_control_support;
|
||||
/* flags */
|
||||
bool thermal_protection;
|
||||
bool pcie_performance_request;
|
||||
bool dynamic_ss;
|
||||
bool dll_default_on;
|
||||
bool cac_enabled;
|
||||
bool uvd_enabled;
|
||||
bool battery_state;
|
||||
bool pspp_notify_required;
|
||||
bool enable_bapm_feature;
|
||||
bool enable_tdc_limit_feature;
|
||||
bool enable_pkg_pwr_tracking_feature;
|
||||
bool use_pcie_performance_levels;
|
||||
bool use_pcie_powersaving_levels;
|
||||
bool uvd_power_gated;
|
||||
/* driver states */
|
||||
struct amdgpu_ps current_rps;
|
||||
struct ci_ps current_ps;
|
||||
struct amdgpu_ps requested_rps;
|
||||
struct ci_ps requested_ps;
|
||||
/* fan control */
|
||||
bool fan_ctrl_is_in_default_mode;
|
||||
bool fan_is_controlled_by_smc;
|
||||
u32 t_min;
|
||||
u32 fan_ctrl_default_mode;
|
||||
};
|
||||
|
||||
#define CISLANDS_VOLTAGE_CONTROL_NONE 0x0
|
||||
#define CISLANDS_VOLTAGE_CONTROL_BY_GPIO 0x1
|
||||
#define CISLANDS_VOLTAGE_CONTROL_BY_SVID2 0x2
|
||||
|
||||
#define CISLANDS_Q88_FORMAT_CONVERSION_UNIT 256
|
||||
|
||||
#define CISLANDS_VRC_DFLT0 0x3FFFC000
|
||||
#define CISLANDS_VRC_DFLT1 0x000400
|
||||
#define CISLANDS_VRC_DFLT2 0xC00080
|
||||
#define CISLANDS_VRC_DFLT3 0xC00200
|
||||
#define CISLANDS_VRC_DFLT4 0xC01680
|
||||
#define CISLANDS_VRC_DFLT5 0xC00033
|
||||
#define CISLANDS_VRC_DFLT6 0xC00033
|
||||
#define CISLANDS_VRC_DFLT7 0x3FFFC000
|
||||
|
||||
#define CISLANDS_CGULVPARAMETER_DFLT 0x00040035
|
||||
#define CISLAND_TARGETACTIVITY_DFLT 30
|
||||
#define CISLAND_MCLK_TARGETACTIVITY_DFLT 10
|
||||
|
||||
#define PCIE_PERF_REQ_REMOVE_REGISTRY 0
|
||||
#define PCIE_PERF_REQ_FORCE_LOWPOWER 1
|
||||
#define PCIE_PERF_REQ_PECI_GEN1 2
|
||||
#define PCIE_PERF_REQ_PECI_GEN2 3
|
||||
#define PCIE_PERF_REQ_PECI_GEN3 4
|
||||
|
||||
#define CISLANDS_SSTU_DFLT 0
|
||||
#define CISLANDS_SST_DFLT 0x00C8
|
||||
|
||||
/* XXX are these ok? */
|
||||
#define CISLANDS_TEMP_RANGE_MIN (90 * 1000)
|
||||
#define CISLANDS_TEMP_RANGE_MAX (120 * 1000)
|
||||
|
||||
int amdgpu_ci_copy_bytes_to_smc(struct amdgpu_device *adev,
|
||||
u32 smc_start_address,
|
||||
const u8 *src, u32 byte_count, u32 limit);
|
||||
void amdgpu_ci_start_smc(struct amdgpu_device *adev);
|
||||
void amdgpu_ci_reset_smc(struct amdgpu_device *adev);
|
||||
int amdgpu_ci_program_jump_on_start(struct amdgpu_device *adev);
|
||||
void amdgpu_ci_stop_smc_clock(struct amdgpu_device *adev);
|
||||
void amdgpu_ci_start_smc_clock(struct amdgpu_device *adev);
|
||||
bool amdgpu_ci_is_smc_running(struct amdgpu_device *adev);
|
||||
PPSMC_Result amdgpu_ci_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg);
|
||||
PPSMC_Result amdgpu_ci_wait_for_smc_inactive(struct amdgpu_device *adev);
|
||||
int amdgpu_ci_load_smc_ucode(struct amdgpu_device *adev, u32 limit);
|
||||
int amdgpu_ci_read_smc_sram_dword(struct amdgpu_device *adev,
|
||||
u32 smc_address, u32 *value, u32 limit);
|
||||
int amdgpu_ci_write_smc_sram_dword(struct amdgpu_device *adev,
|
||||
u32 smc_address, u32 value, u32 limit);
|
||||
|
||||
#endif
|
|
@ -1,279 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011 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.
|
||||
*
|
||||
* Authors: Alex Deucher
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "amdgpu.h"
|
||||
#include "cikd.h"
|
||||
#include "ppsmc.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
#include "ci_dpm.h"
|
||||
|
||||
#include "smu/smu_7_0_1_d.h"
|
||||
#include "smu/smu_7_0_1_sh_mask.h"
|
||||
|
||||
static int ci_set_smc_sram_address(struct amdgpu_device *adev,
|
||||
u32 smc_address, u32 limit)
|
||||
{
|
||||
if (smc_address & 3)
|
||||
return -EINVAL;
|
||||
if ((smc_address + 3) > limit)
|
||||
return -EINVAL;
|
||||
|
||||
WREG32(mmSMC_IND_INDEX_0, smc_address);
|
||||
WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_ci_copy_bytes_to_smc(struct amdgpu_device *adev,
|
||||
u32 smc_start_address,
|
||||
const u8 *src, u32 byte_count, u32 limit)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data, original_data;
|
||||
u32 addr;
|
||||
u32 extra_shift;
|
||||
int ret = 0;
|
||||
|
||||
if (smc_start_address & 3)
|
||||
return -EINVAL;
|
||||
if ((smc_start_address + byte_count) > limit)
|
||||
return -EINVAL;
|
||||
|
||||
addr = smc_start_address;
|
||||
|
||||
spin_lock_irqsave(&adev->smc_idx_lock, flags);
|
||||
while (byte_count >= 4) {
|
||||
/* SMC address space is BE */
|
||||
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
||||
|
||||
ret = ci_set_smc_sram_address(adev, addr, limit);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
WREG32(mmSMC_IND_DATA_0, data);
|
||||
|
||||
src += 4;
|
||||
byte_count -= 4;
|
||||
addr += 4;
|
||||
}
|
||||
|
||||
/* RMW for the final bytes */
|
||||
if (byte_count > 0) {
|
||||
data = 0;
|
||||
|
||||
ret = ci_set_smc_sram_address(adev, addr, limit);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
original_data = RREG32(mmSMC_IND_DATA_0);
|
||||
|
||||
extra_shift = 8 * (4 - byte_count);
|
||||
|
||||
while (byte_count > 0) {
|
||||
data = (data << 8) + *src++;
|
||||
byte_count--;
|
||||
}
|
||||
|
||||
data <<= extra_shift;
|
||||
|
||||
data |= (original_data & ~((~0UL) << extra_shift));
|
||||
|
||||
ret = ci_set_smc_sram_address(adev, addr, limit);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
WREG32(mmSMC_IND_DATA_0, data);
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_ci_start_smc(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
|
||||
|
||||
tmp &= ~SMC_SYSCON_RESET_CNTL__rst_reg_MASK;
|
||||
WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, tmp);
|
||||
}
|
||||
|
||||
void amdgpu_ci_reset_smc(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
|
||||
|
||||
tmp |= SMC_SYSCON_RESET_CNTL__rst_reg_MASK;
|
||||
WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, tmp);
|
||||
}
|
||||
|
||||
int amdgpu_ci_program_jump_on_start(struct amdgpu_device *adev)
|
||||
{
|
||||
static u8 data[] = { 0xE0, 0x00, 0x80, 0x40 };
|
||||
|
||||
return amdgpu_ci_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1);
|
||||
}
|
||||
|
||||
void amdgpu_ci_stop_smc_clock(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
|
||||
tmp |= SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK;
|
||||
|
||||
WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, tmp);
|
||||
}
|
||||
|
||||
void amdgpu_ci_start_smc_clock(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
|
||||
tmp &= ~SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK;
|
||||
|
||||
WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, tmp);
|
||||
}
|
||||
|
||||
bool amdgpu_ci_is_smc_running(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 clk = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
u32 pc_c = RREG32_SMC(ixSMC_PC_C);
|
||||
|
||||
if (!(clk & SMC_SYSCON_CLOCK_CNTL_0__ck_disable_MASK) && (0x20100 <= pc_c))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PPSMC_Result amdgpu_ci_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg)
|
||||
{
|
||||
u32 tmp;
|
||||
int i;
|
||||
|
||||
if (!amdgpu_ci_is_smc_running(adev))
|
||||
return PPSMC_Result_Failed;
|
||||
|
||||
WREG32(mmSMC_MESSAGE_0, msg);
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32(mmSMC_RESP_0);
|
||||
if (tmp != 0)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
tmp = RREG32(mmSMC_RESP_0);
|
||||
|
||||
return (PPSMC_Result)tmp;
|
||||
}
|
||||
|
||||
PPSMC_Result amdgpu_ci_wait_for_smc_inactive(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp;
|
||||
int i;
|
||||
|
||||
if (!amdgpu_ci_is_smc_running(adev))
|
||||
return PPSMC_Result_OK;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
tmp = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
if ((tmp & SMC_SYSCON_CLOCK_CNTL_0__cken_MASK) == 0)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
return PPSMC_Result_OK;
|
||||
}
|
||||
|
||||
int amdgpu_ci_load_smc_ucode(struct amdgpu_device *adev, u32 limit)
|
||||
{
|
||||
const struct smc_firmware_header_v1_0 *hdr;
|
||||
unsigned long flags;
|
||||
u32 ucode_start_address;
|
||||
u32 ucode_size;
|
||||
const u8 *src;
|
||||
u32 data;
|
||||
|
||||
if (!adev->pm.fw)
|
||||
return -EINVAL;
|
||||
|
||||
hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
|
||||
amdgpu_ucode_print_smc_hdr(&hdr->header);
|
||||
|
||||
adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
|
||||
ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
|
||||
ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
|
||||
src = (const u8 *)
|
||||
(adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
|
||||
|
||||
if (ucode_size & 3)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&adev->smc_idx_lock, flags);
|
||||
WREG32(mmSMC_IND_INDEX_0, ucode_start_address);
|
||||
WREG32_P(mmSMC_IND_ACCESS_CNTL, SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK,
|
||||
~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
|
||||
while (ucode_size >= 4) {
|
||||
/* SMC address space is BE */
|
||||
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
|
||||
|
||||
WREG32(mmSMC_IND_DATA_0, data);
|
||||
|
||||
src += 4;
|
||||
ucode_size -= 4;
|
||||
}
|
||||
WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
|
||||
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_ci_read_smc_sram_dword(struct amdgpu_device *adev,
|
||||
u32 smc_address, u32 *value, u32 limit)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&adev->smc_idx_lock, flags);
|
||||
ret = ci_set_smc_sram_address(adev, smc_address, limit);
|
||||
if (ret == 0)
|
||||
*value = RREG32(mmSMC_IND_DATA_0);
|
||||
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_ci_write_smc_sram_dword(struct amdgpu_device *adev,
|
||||
u32 smc_address, u32 value, u32 limit)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&adev->smc_idx_lock, flags);
|
||||
ret = ci_set_smc_sram_address(adev, smc_address, limit);
|
||||
if (ret == 0)
|
||||
WREG32(mmSMC_IND_DATA_0, value);
|
||||
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1741,6 +1741,69 @@ static bool cik_need_full_reset(struct amdgpu_device *adev)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void cik_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
||||
uint64_t *count1)
|
||||
{
|
||||
uint32_t perfctr = 0;
|
||||
uint64_t cnt0_of, cnt1_of;
|
||||
int tmp;
|
||||
|
||||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
|
||||
|
||||
/* Write to enable desired perf counters */
|
||||
WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
|
||||
/* Zero out and enable the perf counters
|
||||
* Write 0x5:
|
||||
* Bit 0 = Start all counters(1)
|
||||
* Bit 2 = Global counter reset enable(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
/* Load the shadow and disable the perf counters
|
||||
* Write 0x2:
|
||||
* Bit 0 = Stop counters(0)
|
||||
* Bit 1 = Load the shadow counters(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
|
||||
|
||||
/* Read register values to get any >32bit overflow */
|
||||
tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
|
||||
cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
|
||||
cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
|
||||
|
||||
/* Get the values and add the overflow */
|
||||
*count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
|
||||
*count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
|
||||
}
|
||||
|
||||
static bool cik_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 clock_cntl, pc;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
|
||||
/* check if the SMC is already running */
|
||||
clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
pc = RREG32_SMC(ixSMC_PC_C);
|
||||
if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) &&
|
||||
(0x20100 <= pc))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct amdgpu_asic_funcs cik_asic_funcs =
|
||||
{
|
||||
.read_disabled_bios = &cik_read_disabled_bios,
|
||||
|
@ -1756,6 +1819,8 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
|
|||
.invalidate_hdp = &cik_invalidate_hdp,
|
||||
.need_full_reset = &cik_need_full_reset,
|
||||
.init_doorbell_index = &legacy_doorbell_index_init,
|
||||
.get_pcie_usage = &cik_get_pcie_usage,
|
||||
.need_reset_on_init = &cik_need_reset_on_init,
|
||||
};
|
||||
|
||||
static int cik_common_early_init(void *handle)
|
||||
|
@ -2005,10 +2070,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
|
||||
if (amdgpu_dpm == -1)
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &ci_smu_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
|
@ -2026,10 +2088,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v7_3_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
|
||||
if (amdgpu_dpm == -1)
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &ci_smu_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#ifndef __CIK_DPM_H__
|
||||
#define __CIK_DPM_H__
|
||||
|
||||
extern const struct amdgpu_ip_block_version ci_smu_ip_block;
|
||||
extern const struct amdgpu_ip_block_version kv_smu_ip_block;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -103,9 +103,9 @@ static void cik_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int cik_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
int rb_bufsz;
|
||||
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
|
||||
u64 wptr_off;
|
||||
|
||||
/* disable irqs */
|
||||
cik_ih_disable_interrupts(adev);
|
||||
|
@ -131,9 +131,8 @@ static int cik_ih_irq_init(struct amdgpu_device *adev)
|
|||
ih_rb_cntl |= IH_RB_CNTL__WPTR_WRITEBACK_ENABLE_MASK;
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
|
||||
|
||||
WREG32(mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
|
@ -183,11 +182,12 @@ static void cik_ih_irq_disable(struct amdgpu_device *adev)
|
|||
* Used by cik_irq_process().
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 cik_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
|
||||
wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
|
||||
|
@ -196,13 +196,13 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
|
||||
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
|
||||
wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
|
||||
ih->rptr = (wptr + 16) & ih->ptr_mask;
|
||||
tmp = RREG32(mmIH_RB_CNTL);
|
||||
tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
|
||||
WREG32(mmIH_RB_CNTL, tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/* CIK IV Ring
|
||||
|
@ -237,16 +237,17 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* position and also advance the position.
|
||||
*/
|
||||
static void cik_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[4];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
|
||||
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
entry->src_id = dw[0] & 0xff;
|
||||
|
@ -256,7 +257,7 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->pasid = (dw[2] >> 16) & 0xffff;
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
adev->irq.ih.rptr += 16;
|
||||
ih->rptr += 16;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -266,9 +267,10 @@ static void cik_ih_decode_iv(struct amdgpu_device *adev,
|
|||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void cik_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void cik_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
|
||||
WREG32(mmIH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
|
||||
static int cik_ih_early_init(void *handle)
|
||||
|
|
|
@ -220,7 +220,7 @@ static void cik_sdma_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 extra_bits = vmid & 0xf;
|
||||
|
|
|
@ -103,9 +103,9 @@ static void cz_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int cz_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int rb_bufsz;
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
|
||||
u64 wptr_off;
|
||||
int rb_bufsz;
|
||||
|
||||
/* disable irqs */
|
||||
cz_ih_disable_interrupts(adev);
|
||||
|
@ -133,9 +133,8 @@ static int cz_ih_irq_init(struct amdgpu_device *adev)
|
|||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
|
||||
|
||||
WREG32(mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
|
@ -185,11 +184,12 @@ static void cz_ih_irq_disable(struct amdgpu_device *adev)
|
|||
* Used by cz_irq_process(VI).
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 cz_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
|
@ -198,13 +198,13 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
|
||||
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
|
||||
wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
|
||||
ih->rptr = (wptr + 16) & ih->ptr_mask;
|
||||
tmp = RREG32(mmIH_RB_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32(mmIH_RB_CNTL, tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,16 +216,17 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* position and also advance the position.
|
||||
*/
|
||||
static void cz_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[4];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
|
||||
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
entry->src_id = dw[0] & 0xff;
|
||||
|
@ -235,7 +236,7 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->pasid = (dw[2] >> 16) & 0xffff;
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
adev->irq.ih.rptr += 16;
|
||||
ih->rptr += 16;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,9 +246,10 @@ static void cz_ih_decode_iv(struct amdgpu_device *adev,
|
|||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void cz_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void cz_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
|
||||
WREG32(mmIH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
|
||||
static int cz_ih_early_init(void *handle)
|
||||
|
|
|
@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
|
|||
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||
|
||||
dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
if (crtc->primary->fb) {
|
||||
int r;
|
||||
struct amdgpu_bo *abo;
|
||||
|
||||
abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]);
|
||||
r = amdgpu_bo_reserve(abo, true);
|
||||
if (unlikely(r))
|
||||
DRM_ERROR("failed to reserve abo before unpin\n");
|
||||
else {
|
||||
amdgpu_bo_unpin(abo);
|
||||
amdgpu_bo_unreserve(abo);
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
|
||||
amdgpu_crtc->encoder = NULL;
|
||||
|
@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,
|
|||
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
|
||||
|
||||
drm_crtc_vblank_put(&amdgpu_crtc->base);
|
||||
schedule_work(&works->unpin_work);
|
||||
amdgpu_bo_unref(&works->old_abo);
|
||||
kfree(works->shared);
|
||||
kfree(works);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1842,13 +1842,13 @@ static void gfx_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
|
|||
static void gfx_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 header, control = 0;
|
||||
|
||||
/* insert SWITCH_BUFFER packet before first IB in the ring frame */
|
||||
if (ctx_switch) {
|
||||
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
|
|
@ -2228,13 +2228,13 @@ static void gfx_v7_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
|
|||
static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 header, control = 0;
|
||||
|
||||
/* insert SWITCH_BUFFER packet before first IB in the ring frame */
|
||||
if (ctx_switch) {
|
||||
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
}
|
||||
|
@ -2259,7 +2259,7 @@ static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
|||
static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
|
||||
|
|
|
@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
u32 tmp;
|
||||
u32 rb_bufsz;
|
||||
u64 rb_addr, rptr_addr, wptr_gpu_addr;
|
||||
int r;
|
||||
|
||||
/* Set the write pointer delay */
|
||||
WREG32(mmCP_RB_WPTR_DELAY, 0);
|
||||
|
@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
|
|||
amdgpu_ring_clear_ring(ring);
|
||||
gfx_v8_0_cp_gfx_start(adev);
|
||||
ring->sched.ready = true;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
|
||||
|
@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
|
|||
amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
|
||||
}
|
||||
|
||||
r = amdgpu_ring_test_helper(kiq_ring);
|
||||
if (r)
|
||||
DRM_ERROR("KCQ enable failed\n");
|
||||
return r;
|
||||
amdgpu_ring_commit(kiq_ring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
|
||||
|
@ -4709,18 +4706,34 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)
|
|||
if (r)
|
||||
goto done;
|
||||
|
||||
/* Test KCQs - reversing the order of rings seems to fix ring test failure
|
||||
* after GPU reset
|
||||
*/
|
||||
for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
done:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
|
||||
{
|
||||
int r, i;
|
||||
struct amdgpu_ring *ring;
|
||||
|
||||
/* collect all the ring_tests here, gfx, kiq, compute */
|
||||
ring = &adev->gfx.gfx_ring[0];
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ring = &adev->gfx.kiq.ring;
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
|
||||
ring = &adev->gfx.compute_ring[i];
|
||||
amdgpu_ring_test_helper(ring);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
|
|||
r = gfx_v8_0_kcq_resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = gfx_v8_0_cp_test_all_rings(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
gfx_v8_0_enable_gui_idle_interrupt(adev, true);
|
||||
|
||||
return 0;
|
||||
|
@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
|
|||
REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))
|
||||
gfx_v8_0_cp_gfx_resume(adev);
|
||||
|
||||
gfx_v8_0_cp_test_all_rings(adev);
|
||||
|
||||
adev->gfx.rlc.funcs->start(adev);
|
||||
|
||||
return 0;
|
||||
|
@ -6027,7 +6047,7 @@ static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
|
|||
static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 header, control = 0;
|
||||
|
@ -6059,7 +6079,7 @@ static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
|||
static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
|
||||
|
|
|
@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
|
|||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff)
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
|
||||
};
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
|
||||
|
@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
|
|||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
|
||||
};
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
|
||||
|
@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
|
|||
{
|
||||
uint32_t data, def;
|
||||
|
||||
amdgpu_gfx_rlc_enter_safe_mode(adev);
|
||||
|
||||
/* It is disabled by HW by default */
|
||||
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
|
||||
/* 1 - RLC_CGTT_MGCG_OVERRIDE */
|
||||
|
@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
|
|||
WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_gfx_rlc_exit_safe_mode(adev);
|
||||
}
|
||||
|
||||
static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
|
||||
|
@ -3968,7 +3972,7 @@ static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
|
|||
static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 header, control = 0;
|
||||
|
@ -4001,7 +4005,7 @@ static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
|||
static void gfx_v9_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
|
||||
|
|
|
@ -1471,8 +1471,9 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
|
|||
gmc_v8_0_set_fault_enable_default(adev, false);
|
||||
|
||||
if (printk_ratelimit()) {
|
||||
struct amdgpu_task_info task_info = { 0 };
|
||||
struct amdgpu_task_info task_info;
|
||||
|
||||
memset(&task_info, 0, sizeof(struct amdgpu_task_info));
|
||||
amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
|
||||
|
||||
dev_err(adev->dev, "GPU fault detected: %d 0x%08x for process %s pid %d thread %s pid %d\n",
|
||||
|
|
|
@ -305,6 +305,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
|
|||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[entry->vmid_src];
|
||||
bool retry_fault = !!(entry->src_data[1] & 0x80);
|
||||
uint32_t status = 0;
|
||||
u64 addr;
|
||||
|
||||
|
@ -320,13 +321,16 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
if (printk_ratelimit()) {
|
||||
struct amdgpu_task_info task_info = { 0 };
|
||||
struct amdgpu_task_info task_info;
|
||||
|
||||
memset(&task_info, 0, sizeof(struct amdgpu_task_info));
|
||||
amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
|
||||
|
||||
dev_err(adev->dev,
|
||||
"[%s] VMC page fault (src_id:%u ring:%u vmid:%u pasid:%u, for process %s pid %d thread %s pid %d)\n",
|
||||
"[%s] %s page fault (src_id:%u ring:%u vmid:%u "
|
||||
"pasid:%u, for process %s pid %d thread %s pid %d)\n",
|
||||
entry->vmid_src ? "mmhub" : "gfxhub",
|
||||
retry_fault ? "retry" : "no-retry",
|
||||
entry->src_id, entry->ring_id, entry->vmid,
|
||||
entry->pasid, task_info.process_name, task_info.tgid,
|
||||
task_info.task_name, task_info.pid);
|
||||
|
|
|
@ -103,9 +103,9 @@ static void iceland_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int iceland_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
int rb_bufsz;
|
||||
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
|
||||
u64 wptr_off;
|
||||
|
||||
/* disable irqs */
|
||||
iceland_ih_disable_interrupts(adev);
|
||||
|
@ -133,9 +133,8 @@ static int iceland_ih_irq_init(struct amdgpu_device *adev)
|
|||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
|
||||
|
||||
WREG32(mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
|
@ -185,11 +184,12 @@ static void iceland_ih_irq_disable(struct amdgpu_device *adev)
|
|||
* Used by cz_irq_process(VI).
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 iceland_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
|
@ -198,13 +198,13 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
|
||||
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
|
||||
wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
|
||||
ih->rptr = (wptr + 16) & ih->ptr_mask;
|
||||
tmp = RREG32(mmIH_RB_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32(mmIH_RB_CNTL, tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,16 +216,17 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* position and also advance the position.
|
||||
*/
|
||||
static void iceland_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[4];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
|
||||
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
entry->src_id = dw[0] & 0xff;
|
||||
|
@ -235,7 +236,7 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->pasid = (dw[2] >> 16) & 0xffff;
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
adev->irq.ih.rptr += 16;
|
||||
ih->rptr += 16;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,9 +246,10 @@ static void iceland_ih_decode_iv(struct amdgpu_device *adev,
|
|||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void iceland_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void iceland_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
|
||||
WREG32(mmIH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
|
||||
static int iceland_ih_early_init(void *handle)
|
||||
|
|
|
@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
|
|||
return r;
|
||||
}
|
||||
/* Retrieve checksum from mailbox2 */
|
||||
if (req == IDH_REQ_GPU_INIT_ACCESS) {
|
||||
if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {
|
||||
adev->virt.fw_reserve.checksum_key =
|
||||
RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
|
||||
mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2));
|
||||
|
|
|
@ -27,13 +27,9 @@
|
|||
#include "nbio/nbio_6_1_default.h"
|
||||
#include "nbio/nbio_6_1_offset.h"
|
||||
#include "nbio/nbio_6_1_sh_mask.h"
|
||||
#include "nbio/nbio_6_1_smn.h"
|
||||
#include "vega10_enum.h"
|
||||
|
||||
#define smnCPM_CONTROL 0x11180460
|
||||
#define smnPCIE_CNTL2 0x11180070
|
||||
#define smnPCIE_CONFIG_CNTL 0x11180044
|
||||
#define smnPCIE_CI_CNTL 0x11180080
|
||||
|
||||
static u32 nbio_v6_1_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
|
||||
|
@ -72,7 +68,7 @@ static u32 nbio_v6_1_get_memsize(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
static void nbio_v6_1_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index)
|
||||
bool use_doorbell, int doorbell_index, int doorbell_size)
|
||||
{
|
||||
u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
|
||||
SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
|
||||
|
@ -81,7 +77,7 @@ static void nbio_v6_1_sdma_doorbell_range(struct amdgpu_device *adev, int instan
|
|||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
|
||||
} else
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
|
||||
|
||||
|
|
|
@ -27,13 +27,11 @@
|
|||
#include "nbio/nbio_7_0_default.h"
|
||||
#include "nbio/nbio_7_0_offset.h"
|
||||
#include "nbio/nbio_7_0_sh_mask.h"
|
||||
#include "nbio/nbio_7_0_smn.h"
|
||||
#include "vega10_enum.h"
|
||||
|
||||
#define smnNBIF_MGCG_CTRL_LCLK 0x1013a05c
|
||||
|
||||
#define smnCPM_CONTROL 0x11180460
|
||||
#define smnPCIE_CNTL2 0x11180070
|
||||
|
||||
static u32 nbio_v7_0_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
|
||||
|
@ -69,7 +67,7 @@ static u32 nbio_v7_0_get_memsize(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
static void nbio_v7_0_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index)
|
||||
bool use_doorbell, int doorbell_index, int doorbell_size)
|
||||
{
|
||||
u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
|
||||
SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
|
||||
|
@ -78,7 +76,7 @@ static void nbio_v7_0_sdma_doorbell_range(struct amdgpu_device *adev, int instan
|
|||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
|
||||
} else
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
|
||||
|
||||
|
|
|
@ -26,13 +26,10 @@
|
|||
|
||||
#include "nbio/nbio_7_4_offset.h"
|
||||
#include "nbio/nbio_7_4_sh_mask.h"
|
||||
#include "nbio/nbio_7_4_0_smn.h"
|
||||
|
||||
#define smnNBIF_MGCG_CTRL_LCLK 0x1013a21c
|
||||
|
||||
#define smnCPM_CONTROL 0x11180460
|
||||
#define smnPCIE_CNTL2 0x11180070
|
||||
#define smnPCIE_CI_CNTL 0x11180080
|
||||
|
||||
static u32 nbio_v7_4_get_rev_id(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 tmp = RREG32_SOC15(NBIO, 0, mmRCC_DEV0_EPF0_STRAP0);
|
||||
|
@ -68,7 +65,7 @@ static u32 nbio_v7_4_get_memsize(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
static void nbio_v7_4_sdma_doorbell_range(struct amdgpu_device *adev, int instance,
|
||||
bool use_doorbell, int doorbell_index)
|
||||
bool use_doorbell, int doorbell_index, int doorbell_size)
|
||||
{
|
||||
u32 reg = instance == 0 ? SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA0_DOORBELL_RANGE) :
|
||||
SOC15_REG_OFFSET(NBIO, 0, mmBIF_SDMA1_DOORBELL_RANGE);
|
||||
|
@ -77,7 +74,7 @@ static void nbio_v7_4_sdma_doorbell_range(struct amdgpu_device *adev, int instan
|
|||
|
||||
if (use_doorbell) {
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, OFFSET, doorbell_index);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 2);
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, doorbell_size);
|
||||
} else
|
||||
doorbell_range = REG_SET_FIELD(doorbell_range, BIF_SDMA0_DOORBELL_RANGE, SIZE, 0);
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ enum psp_gfx_fw_type
|
|||
GFX_FW_TYPE_MMSCH = 19,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM = 20,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM = 21,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL = 22,
|
||||
GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL = 22,
|
||||
GFX_FW_TYPE_UVD1 = 23,
|
||||
GFX_FW_TYPE_MAX = 24
|
||||
};
|
||||
|
|
|
@ -38,75 +38,6 @@ MODULE_FIRMWARE("amdgpu/raven_asd.bin");
|
|||
MODULE_FIRMWARE("amdgpu/picasso_asd.bin");
|
||||
MODULE_FIRMWARE("amdgpu/raven2_asd.bin");
|
||||
|
||||
static int
|
||||
psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
|
||||
{
|
||||
switch(ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*type = GFX_FW_TYPE_SDMA0;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SDMA1:
|
||||
*type = GFX_FW_TYPE_SDMA1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_CE:
|
||||
*type = GFX_FW_TYPE_CP_CE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_PFP:
|
||||
*type = GFX_FW_TYPE_CP_PFP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_ME:
|
||||
*type = GFX_FW_TYPE_CP_ME;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME2;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
*type = GFX_FW_TYPE_RLC_G;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_CNTL;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
|
||||
*type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SMC:
|
||||
*type = GFX_FW_TYPE_SMU;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD:
|
||||
*type = GFX_FW_TYPE_UVD;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCE:
|
||||
*type = GFX_FW_TYPE_VCE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCN:
|
||||
*type = GFX_FW_TYPE_VCN;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_DMCU_ERAM:
|
||||
*type = GFX_FW_TYPE_DMCU_ERAM;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_DMCU_INTV:
|
||||
*type = GFX_FW_TYPE_DMCU_ISR;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
@ -158,26 +89,6 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int psp_v10_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
|
||||
struct psp_gfx_cmd_resp *cmd)
|
||||
{
|
||||
int ret;
|
||||
uint64_t fw_mem_mc_addr = ucode->mc_addr;
|
||||
|
||||
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
|
||||
|
||||
ret = psp_v10_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
|
||||
if (ret)
|
||||
DRM_ERROR("Unknown firmware type\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v10_0_ring_init(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type)
|
||||
{
|
||||
|
@ -454,7 +365,6 @@ static int psp_v10_0_mode1_reset(struct psp_context *psp)
|
|||
|
||||
static const struct psp_funcs psp_v10_0_funcs = {
|
||||
.init_microcode = psp_v10_0_init_microcode,
|
||||
.prep_cmd_buf = psp_v10_0_prep_cmd_buf,
|
||||
.ring_init = psp_v10_0_ring_init,
|
||||
.ring_create = psp_v10_0_ring_create,
|
||||
.ring_stop = psp_v10_0_ring_stop,
|
||||
|
|
|
@ -40,60 +40,6 @@ MODULE_FIRMWARE("amdgpu/vega20_ta.bin");
|
|||
/* address block */
|
||||
#define smnMP1_FIRMWARE_FLAGS 0x3010024
|
||||
|
||||
static int
|
||||
psp_v11_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
|
||||
{
|
||||
switch (ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*type = GFX_FW_TYPE_SDMA0;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SDMA1:
|
||||
*type = GFX_FW_TYPE_SDMA1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_CE:
|
||||
*type = GFX_FW_TYPE_CP_CE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_PFP:
|
||||
*type = GFX_FW_TYPE_CP_PFP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_ME:
|
||||
*type = GFX_FW_TYPE_CP_ME;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME2;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
*type = GFX_FW_TYPE_RLC_G;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SMC:
|
||||
*type = GFX_FW_TYPE_SMU;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD:
|
||||
*type = GFX_FW_TYPE_UVD;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCE:
|
||||
*type = GFX_FW_TYPE_VCE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD1:
|
||||
*type = GFX_FW_TYPE_UVD1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
@ -267,26 +213,6 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v11_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
|
||||
struct psp_gfx_cmd_resp *cmd)
|
||||
{
|
||||
int ret;
|
||||
uint64_t fw_mem_mc_addr = ucode->mc_addr;
|
||||
|
||||
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
|
||||
|
||||
ret = psp_v11_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
|
||||
if (ret)
|
||||
DRM_ERROR("Unknown firmware type\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v11_0_ring_init(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type)
|
||||
{
|
||||
|
@ -753,7 +679,6 @@ static const struct psp_funcs psp_v11_0_funcs = {
|
|||
.init_microcode = psp_v11_0_init_microcode,
|
||||
.bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
|
||||
.bootloader_load_sos = psp_v11_0_bootloader_load_sos,
|
||||
.prep_cmd_buf = psp_v11_0_prep_cmd_buf,
|
||||
.ring_init = psp_v11_0_ring_init,
|
||||
.ring_create = psp_v11_0_ring_create,
|
||||
.ring_stop = psp_v11_0_ring_stop,
|
||||
|
|
|
@ -47,57 +47,6 @@ MODULE_FIRMWARE("amdgpu/vega12_asd.bin");
|
|||
|
||||
static uint32_t sos_old_versions[] = {1517616, 1510592, 1448594, 1446554};
|
||||
|
||||
static int
|
||||
psp_v3_1_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
|
||||
{
|
||||
switch(ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
*type = GFX_FW_TYPE_SDMA0;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SDMA1:
|
||||
*type = GFX_FW_TYPE_SDMA1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_CE:
|
||||
*type = GFX_FW_TYPE_CP_CE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_PFP:
|
||||
*type = GFX_FW_TYPE_CP_PFP;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_ME:
|
||||
*type = GFX_FW_TYPE_CP_ME;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC1_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME1;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2:
|
||||
*type = GFX_FW_TYPE_CP_MEC;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_CP_MEC2_JT:
|
||||
*type = GFX_FW_TYPE_CP_MEC_ME2;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
*type = GFX_FW_TYPE_RLC_G;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_SMC:
|
||||
*type = GFX_FW_TYPE_SMU;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_UVD:
|
||||
*type = GFX_FW_TYPE_UVD;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_VCE:
|
||||
*type = GFX_FW_TYPE_VCE;
|
||||
break;
|
||||
case AMDGPU_UCODE_ID_MAXIMUM:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psp_v3_1_init_microcode(struct psp_context *psp)
|
||||
{
|
||||
struct amdgpu_device *adev = psp->adev;
|
||||
|
@ -277,26 +226,6 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
|
||||
struct psp_gfx_cmd_resp *cmd)
|
||||
{
|
||||
int ret;
|
||||
uint64_t fw_mem_mc_addr = ucode->mc_addr;
|
||||
|
||||
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
|
||||
cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
|
||||
|
||||
ret = psp_v3_1_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
|
||||
if (ret)
|
||||
DRM_ERROR("Unknown firmware type\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_v3_1_ring_init(struct psp_context *psp,
|
||||
enum psp_ring_type ring_type)
|
||||
{
|
||||
|
@ -615,7 +544,6 @@ 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,
|
||||
.bootloader_load_sos = psp_v3_1_bootloader_load_sos,
|
||||
.prep_cmd_buf = psp_v3_1_prep_cmd_buf,
|
||||
.ring_init = psp_v3_1_ring_init,
|
||||
.ring_create = psp_v3_1_ring_create,
|
||||
.ring_stop = psp_v3_1_ring_stop,
|
||||
|
|
|
@ -247,7 +247,7 @@ static void sdma_v2_4_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ static void sdma_v3_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
@ -1145,8 +1145,7 @@ static int sdma_v3_0_sw_init(void *handle)
|
|||
ring->ring_obj = NULL;
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = (i == 0) ?
|
||||
adev->doorbell_index.sdma_engine0 : adev->doorbell_index.sdma_engine1;
|
||||
ring->doorbell_index = adev->doorbell_index.sdma_engine[i];
|
||||
} else {
|
||||
ring->use_pollmem = true;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
|
|||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
|
||||
|
@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
|
|||
static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
|
||||
};
|
||||
|
@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
|
|||
static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
|
||||
SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
|
||||
};
|
||||
|
@ -499,7 +500,7 @@ static void sdma_v4_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
|
|||
static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
@ -833,8 +834,6 @@ static void sdma_v4_0_gfx_resume(struct amdgpu_device *adev, unsigned int i)
|
|||
OFFSET, ring->doorbell_index);
|
||||
WREG32_SDMA(i, mmSDMA0_GFX_DOORBELL, doorbell);
|
||||
WREG32_SDMA(i, mmSDMA0_GFX_DOORBELL_OFFSET, doorbell_offset);
|
||||
adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell,
|
||||
ring->doorbell_index);
|
||||
|
||||
sdma_v4_0_ring_set_wptr(ring);
|
||||
|
||||
|
@ -1521,9 +1520,7 @@ static int sdma_v4_0_sw_init(void *handle)
|
|||
ring->use_doorbell?"true":"false");
|
||||
|
||||
/* doorbell size is 2 dwords, get DWORD offset */
|
||||
ring->doorbell_index = (i == 0) ?
|
||||
(adev->doorbell_index.sdma_engine0 << 1)
|
||||
: (adev->doorbell_index.sdma_engine1 << 1);
|
||||
ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
|
||||
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
|
@ -1542,9 +1539,7 @@ static int sdma_v4_0_sw_init(void *handle)
|
|||
/* paging queue use same doorbell index/routing as gfx queue
|
||||
* with 0x400 (4096 dwords) offset on second doorbell page
|
||||
*/
|
||||
ring->doorbell_index = (i == 0) ?
|
||||
(adev->doorbell_index.sdma_engine0 << 1)
|
||||
: (adev->doorbell_index.sdma_engine1 << 1);
|
||||
ring->doorbell_index = adev->doorbell_index.sdma_engine[i] << 1;
|
||||
ring->doorbell_index += 0x400;
|
||||
|
||||
sprintf(ring->name, "page%d", i);
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "dce/dce_6_0_d.h"
|
||||
#include "uvd/uvd_4_0_d.h"
|
||||
#include "bif/bif_3_0_d.h"
|
||||
#include "bif/bif_3_0_sh_mask.h"
|
||||
|
||||
static const u32 tahiti_golden_registers[] =
|
||||
{
|
||||
|
@ -1258,6 +1259,11 @@ static bool si_need_full_reset(struct amdgpu_device *adev)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool si_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static int si_get_pcie_lanes(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 link_width_cntl;
|
||||
|
@ -1323,6 +1329,52 @@ static void si_set_pcie_lanes(struct amdgpu_device *adev, int lanes)
|
|||
WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
|
||||
}
|
||||
|
||||
static void si_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
||||
uint64_t *count1)
|
||||
{
|
||||
uint32_t perfctr = 0;
|
||||
uint64_t cnt0_of, cnt1_of;
|
||||
int tmp;
|
||||
|
||||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
|
||||
|
||||
/* Write to enable desired perf counters */
|
||||
WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
|
||||
/* Zero out and enable the perf counters
|
||||
* Write 0x5:
|
||||
* Bit 0 = Start all counters(1)
|
||||
* Bit 2 = Global counter reset enable(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
/* Load the shadow and disable the perf counters
|
||||
* Write 0x2:
|
||||
* Bit 0 = Stop counters(0)
|
||||
* Bit 1 = Load the shadow counters(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
|
||||
|
||||
/* Read register values to get any >32bit overflow */
|
||||
tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
|
||||
cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
|
||||
cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
|
||||
|
||||
/* Get the values and add the overflow */
|
||||
*count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
|
||||
*count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
|
||||
}
|
||||
|
||||
static const struct amdgpu_asic_funcs si_asic_funcs =
|
||||
{
|
||||
.read_disabled_bios = &si_read_disabled_bios,
|
||||
|
@ -1339,6 +1391,8 @@ static const struct amdgpu_asic_funcs si_asic_funcs =
|
|||
.flush_hdp = &si_flush_hdp,
|
||||
.invalidate_hdp = &si_invalidate_hdp,
|
||||
.need_full_reset = &si_need_full_reset,
|
||||
.get_pcie_usage = &si_get_pcie_usage,
|
||||
.need_reset_on_init = &si_need_reset_on_init,
|
||||
};
|
||||
|
||||
static uint32_t si_get_rev_id(struct amdgpu_device *adev)
|
||||
|
|
|
@ -63,7 +63,7 @@ static void si_dma_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
static void si_dma_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
/* The indirect buffer packet must end on an 8 DW boundary in the DMA ring.
|
||||
|
|
|
@ -57,9 +57,9 @@ static void si_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
|
||||
static int si_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
int rb_bufsz;
|
||||
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
|
||||
u64 wptr_off;
|
||||
|
||||
si_ih_disable_interrupts(adev);
|
||||
WREG32(INTERRUPT_CNTL2, adev->irq.ih.gpu_addr >> 8);
|
||||
|
@ -76,9 +76,8 @@ static int si_ih_irq_init(struct amdgpu_device *adev)
|
|||
(rb_bufsz << 1) |
|
||||
IH_WPTR_WRITEBACK_ENABLE;
|
||||
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
|
||||
WREG32(IH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
|
||||
WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
|
||||
WREG32(IH_RB_CNTL, ih_rb_cntl);
|
||||
WREG32(IH_RB_RPTR, 0);
|
||||
WREG32(IH_RB_WPTR, 0);
|
||||
|
@ -100,34 +99,36 @@ static void si_ih_irq_disable(struct amdgpu_device *adev)
|
|||
mdelay(1);
|
||||
}
|
||||
|
||||
static u32 si_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 si_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) {
|
||||
wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK;
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
|
||||
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
|
||||
wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
|
||||
ih->rptr = (wptr + 16) & ih->ptr_mask;
|
||||
tmp = RREG32(IH_RB_CNTL);
|
||||
tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
|
||||
WREG32(IH_RB_CNTL, tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
static void si_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[4];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
|
||||
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
entry->src_id = dw[0] & 0xff;
|
||||
|
@ -135,12 +136,13 @@ static void si_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->ring_id = dw[2] & 0xff;
|
||||
entry->vmid = (dw[2] >> 8) & 0xff;
|
||||
|
||||
adev->irq.ih.rptr += 16;
|
||||
ih->rptr += 16;
|
||||
}
|
||||
|
||||
static void si_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void si_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
WREG32(IH_RB_RPTR, adev->irq.ih.rptr);
|
||||
WREG32(IH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
|
||||
static int si_ih_early_init(void *handle)
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
#include "hdp/hdp_4_0_sh_mask.h"
|
||||
#include "smuio/smuio_9_0_offset.h"
|
||||
#include "smuio/smuio_9_0_sh_mask.h"
|
||||
#include "nbio/nbio_7_0_default.h"
|
||||
#include "nbio/nbio_7_0_sh_mask.h"
|
||||
#include "nbio/nbio_7_0_smn.h"
|
||||
#include "mp/mp_9_0_offset.h"
|
||||
|
||||
#include "soc15.h"
|
||||
#include "soc15_common.h"
|
||||
|
@ -385,14 +389,13 @@ void soc15_program_register_sequence(struct amdgpu_device *adev,
|
|||
|
||||
}
|
||||
|
||||
|
||||
static int soc15_asic_reset(struct amdgpu_device *adev)
|
||||
static int soc15_asic_mode1_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
amdgpu_atombios_scratch_regs_engine_hung(adev, true);
|
||||
|
||||
dev_info(adev->dev, "GPU reset\n");
|
||||
dev_info(adev->dev, "GPU mode1 reset\n");
|
||||
|
||||
/* disable BM */
|
||||
pci_clear_master(adev->pdev);
|
||||
|
@ -417,6 +420,63 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int soc15_asic_get_baco_capability(struct amdgpu_device *adev, bool *cap)
|
||||
{
|
||||
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_capability) {
|
||||
*cap = false;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return pp_funcs->get_asic_baco_capability(pp_handle, cap);
|
||||
}
|
||||
|
||||
static int soc15_asic_baco_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
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;
|
||||
|
||||
/* exit BACO state */
|
||||
if (pp_funcs->set_asic_baco_state(pp_handle, 0))
|
||||
return -EIO;
|
||||
|
||||
dev_info(adev->dev, "GPU BACO reset\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int soc15_asic_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret;
|
||||
bool baco_reset;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA20:
|
||||
soc15_asic_get_baco_capability(adev, &baco_reset);
|
||||
break;
|
||||
default:
|
||||
baco_reset = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (baco_reset)
|
||||
ret = soc15_asic_baco_reset(adev);
|
||||
else
|
||||
ret = soc15_asic_mode1_reset(adev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static int soc15_set_uvd_clock(struct amdgpu_device *adev, u32 clock,
|
||||
u32 cntl_reg, u32 status_reg)
|
||||
{
|
||||
|
@ -535,10 +595,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) {
|
||||
if (adev->asic_type == CHIP_VEGA20)
|
||||
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
|
||||
else
|
||||
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
|
||||
}
|
||||
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))
|
||||
|
@ -560,7 +622,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
|
||||
if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP))
|
||||
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
|
||||
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
|
||||
|
@ -601,6 +664,68 @@ static bool soc15_need_full_reset(struct amdgpu_device *adev)
|
|||
/* change this when we implement soft reset */
|
||||
return true;
|
||||
}
|
||||
static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
||||
uint64_t *count1)
|
||||
{
|
||||
uint32_t perfctr = 0;
|
||||
uint64_t cnt0_of, cnt1_of;
|
||||
int tmp;
|
||||
|
||||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
|
||||
|
||||
/* Write to enable desired perf counters */
|
||||
WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK, perfctr);
|
||||
/* Zero out and enable the perf counters
|
||||
* Write 0x5:
|
||||
* Bit 0 = Start all counters(1)
|
||||
* Bit 2 = Global counter reset enable(1)
|
||||
*/
|
||||
WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
/* Load the shadow and disable the perf counters
|
||||
* Write 0x2:
|
||||
* Bit 0 = Stop counters(0)
|
||||
* Bit 1 = Load the shadow counters(1)
|
||||
*/
|
||||
WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002);
|
||||
|
||||
/* Read register values to get any >32bit overflow */
|
||||
tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK);
|
||||
cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
|
||||
cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
|
||||
|
||||
/* Get the values and add the overflow */
|
||||
*count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
|
||||
*count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
|
||||
}
|
||||
|
||||
static bool soc15_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 sol_reg;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
|
||||
/* Check sOS sign of life register to confirm sys driver and sOS
|
||||
* are already been loaded.
|
||||
*/
|
||||
sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
|
||||
if (sol_reg)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct amdgpu_asic_funcs soc15_asic_funcs =
|
||||
{
|
||||
|
@ -617,6 +742,8 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
|
|||
.invalidate_hdp = &soc15_invalidate_hdp,
|
||||
.need_full_reset = &soc15_need_full_reset,
|
||||
.init_doorbell_index = &vega10_doorbell_index_init,
|
||||
.get_pcie_usage = &soc15_get_pcie_usage,
|
||||
.need_reset_on_init = &soc15_need_reset_on_init,
|
||||
};
|
||||
|
||||
static const struct amdgpu_asic_funcs vega20_asic_funcs =
|
||||
|
@ -634,6 +761,8 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
|
|||
.invalidate_hdp = &soc15_invalidate_hdp,
|
||||
.need_full_reset = &soc15_need_full_reset,
|
||||
.init_doorbell_index = &vega20_doorbell_index_init,
|
||||
.get_pcie_usage = &soc15_get_pcie_usage,
|
||||
.need_reset_on_init = &soc15_need_reset_on_init,
|
||||
};
|
||||
|
||||
static int soc15_common_early_init(void *handle)
|
||||
|
@ -840,6 +969,22 @@ static int soc15_common_sw_fini(void *handle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void soc15_doorbell_range_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_ring *ring;
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
ring = &adev->sdma.instance[i].ring;
|
||||
adev->nbio_funcs->sdma_doorbell_range(adev, i,
|
||||
ring->use_doorbell, ring->doorbell_index,
|
||||
adev->doorbell_index.sdma_doorbell_range);
|
||||
}
|
||||
|
||||
adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
|
||||
adev->irq.ih.doorbell_index);
|
||||
}
|
||||
|
||||
static int soc15_common_hw_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
@ -852,6 +997,12 @@ static int soc15_common_hw_init(void *handle)
|
|||
adev->nbio_funcs->init_registers(adev);
|
||||
/* enable the doorbell aperture */
|
||||
soc15_enable_doorbell_aperture(adev, true);
|
||||
/* HW doorbell routing policy: doorbell writing not
|
||||
* in SDMA/IH/MM/ACV range will be routed to CP. So
|
||||
* we need to init SDMA/IH/MM/ACV doorbell range prior
|
||||
* to CP ip block init and ring test.
|
||||
*/
|
||||
soc15_doorbell_range_init(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -99,9 +99,9 @@ static void tonga_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int tonga_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int rb_bufsz;
|
||||
u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr;
|
||||
u64 wptr_off;
|
||||
struct amdgpu_ih_ring *ih = &adev->irq.ih;
|
||||
int rb_bufsz;
|
||||
|
||||
/* disable irqs */
|
||||
tonga_ih_disable_interrupts(adev);
|
||||
|
@ -118,10 +118,7 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev)
|
|||
WREG32(mmINTERRUPT_CNTL, interrupt_cntl);
|
||||
|
||||
/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
WREG32(mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8);
|
||||
else
|
||||
WREG32(mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
|
||||
WREG32(mmIH_RB_BASE, ih->gpu_addr >> 8);
|
||||
|
||||
rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
|
||||
ih_rb_cntl = REG_SET_FIELD(0, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
|
@ -136,12 +133,8 @@ static int tonga_ih_irq_init(struct amdgpu_device *adev)
|
|||
WREG32(mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
else
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
|
||||
WREG32(mmIH_RB_WPTR_ADDR_LO, lower_32_bits(ih->wptr_addr));
|
||||
WREG32(mmIH_RB_WPTR_ADDR_HI, upper_32_bits(ih->wptr_addr) & 0xFF);
|
||||
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32(mmIH_RB_RPTR, 0);
|
||||
|
@ -193,14 +186,12 @@ static void tonga_ih_irq_disable(struct amdgpu_device *adev)
|
|||
* Used by cz_irq_process(VI).
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 tonga_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]);
|
||||
else
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
|
@ -209,13 +200,13 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* this should allow us to catchup.
|
||||
*/
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, (wptr + 16) & adev->irq.ih.ptr_mask);
|
||||
adev->irq.ih.rptr = (wptr + 16) & adev->irq.ih.ptr_mask;
|
||||
wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
|
||||
ih->rptr = (wptr + 16) & ih->ptr_mask;
|
||||
tmp = RREG32(mmIH_RB_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32(mmIH_RB_CNTL, tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,16 +218,17 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* position and also advance the position.
|
||||
*/
|
||||
static void tonga_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[4];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
|
||||
entry->client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
|
||||
entry->src_id = dw[0] & 0xff;
|
||||
|
@ -246,7 +238,7 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->pasid = (dw[2] >> 16) & 0xffff;
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
adev->irq.ih.rptr += 16;
|
||||
ih->rptr += 16;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,17 +248,15 @@ static void tonga_ih_decode_iv(struct amdgpu_device *adev,
|
|||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void tonga_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void tonga_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
if (adev->irq.ih.use_doorbell) {
|
||||
if (ih->use_doorbell) {
|
||||
/* XXX check if swapping is necessary on BE */
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
|
||||
else
|
||||
adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
|
||||
WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr);
|
||||
*ih->rptr_cpu = ih->rptr;
|
||||
WDOORBELL32(ih->doorbell_index, ih->rptr);
|
||||
} else {
|
||||
WREG32(mmIH_RB_RPTR, adev->irq.ih.rptr);
|
||||
WREG32(mmIH_RB_RPTR, ih->rptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -511,7 +511,7 @@ static int uvd_v4_2_ring_test_ring(struct amdgpu_ring *ring)
|
|||
static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_BASE, 0));
|
||||
amdgpu_ring_write(ring, ib->gpu_addr);
|
||||
|
|
|
@ -526,7 +526,7 @@ static int uvd_v5_0_ring_test_ring(struct amdgpu_ring *ring)
|
|||
static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0));
|
||||
amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
|
||||
|
|
|
@ -977,7 +977,7 @@ static int uvd_v6_0_ring_test_ring(struct amdgpu_ring *ring)
|
|||
static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
@ -1003,7 +1003,7 @@ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
|
|||
static void uvd_v6_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
|
|
@ -1272,7 +1272,7 @@ static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
|||
static void uvd_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
@ -1303,7 +1303,7 @@ static void uvd_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
|
|||
static void uvd_v7_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
|
|
@ -834,7 +834,7 @@ static void vce_v3_0_get_clockgating_state(void *handle, u32 *flags)
|
|||
static void vce_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
|
|
@ -947,7 +947,7 @@ static int vce_v4_0_set_powergating_state(void *handle,
|
|||
#endif
|
||||
|
||||
static void vce_v4_0_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib, bool ctx_switch)
|
||||
struct amdgpu_ib *ib, uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
|
|
@ -1371,7 +1371,7 @@ static void vcn_v1_0_dec_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
|
|||
static void vcn_v1_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
@ -1531,7 +1531,7 @@ static void vcn_v1_0_enc_ring_insert_end(struct amdgpu_ring *ring)
|
|||
static void vcn_v1_0_enc_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
||||
|
@ -1736,7 +1736,7 @@ static void vcn_v1_0_jpeg_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u6
|
|||
static void vcn_v1_0_jpeg_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_ib *ib,
|
||||
bool ctx_switch)
|
||||
uint32_t flags)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
unsigned vmid = AMDGPU_JOB_GET_VMID(job);
|
||||
|
|
|
@ -50,6 +50,22 @@ static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
|
|||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
adev->irq.ih.enabled = true;
|
||||
|
||||
if (adev->irq.ih1.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
|
||||
RB_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
adev->irq.ih1.enabled = true;
|
||||
}
|
||||
|
||||
if (adev->irq.ih2.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
|
||||
RB_ENABLE, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
adev->irq.ih2.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,6 +87,53 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
|
||||
adev->irq.ih.enabled = false;
|
||||
adev->irq.ih.rptr = 0;
|
||||
|
||||
if (adev->irq.ih1.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
|
||||
RB_ENABLE, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
|
||||
adev->irq.ih1.enabled = false;
|
||||
adev->irq.ih1.rptr = 0;
|
||||
}
|
||||
|
||||
if (adev->irq.ih2.ring_size) {
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
|
||||
RB_ENABLE, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
|
||||
adev->irq.ih2.enabled = false;
|
||||
adev->irq.ih2.rptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
|
||||
{
|
||||
int rb_bufsz = order_base_2(ih->ring_size / 4);
|
||||
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
MC_SPACE, ih->use_bus_addr ? 1 : 4);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_OVERFLOW_CLEAR, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_OVERFLOW_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
|
||||
/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
|
||||
* value is written to memory
|
||||
*/
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
|
||||
WPTR_WRITEBACK_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
|
||||
|
||||
return ih_rb_cntl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,50 +149,32 @@ static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
|
|||
*/
|
||||
static int vega10_ih_irq_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_ih_ring *ih;
|
||||
int ret = 0;
|
||||
int rb_bufsz;
|
||||
u32 ih_rb_cntl, ih_doorbell_rtpr;
|
||||
u32 tmp;
|
||||
u64 wptr_off;
|
||||
|
||||
/* disable irqs */
|
||||
vega10_ih_disable_interrupts(adev);
|
||||
|
||||
adev->nbio_funcs->ih_control(adev);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
ih = &adev->irq.ih;
|
||||
/* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
|
||||
if (adev->irq.ih.use_bus_addr) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.rb_dma_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, ((u64)adev->irq.ih.rb_dma_addr >> 40) & 0xff);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 1);
|
||||
} else {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, adev->irq.ih.gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (adev->irq.ih.gpu_addr >> 40) & 0xff);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SPACE, 4);
|
||||
}
|
||||
rb_bufsz = order_base_2(adev->irq.ih.ring_size / 4);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
|
||||
/* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register value is written to memory */
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, WPTR_WRITEBACK_ENABLE, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
|
||||
|
||||
if (adev->irq.msi_enabled)
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM, 1);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
|
||||
!!adev->irq.msi_enabled);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
|
||||
|
||||
/* set the writeback address whether it's enabled or not */
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
wptr_off = adev->irq.ih.rb_dma_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
else
|
||||
wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFFFF);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
|
||||
lower_32_bits(ih->wptr_addr));
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
|
||||
upper_32_bits(ih->wptr_addr) & 0xFFFF);
|
||||
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
|
||||
|
@ -137,17 +182,48 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
|
|||
|
||||
ih_doorbell_rtpr = RREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR);
|
||||
if (adev->irq.ih.use_doorbell) {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
|
||||
OFFSET, adev->irq.ih.doorbell_index);
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR, OFFSET,
|
||||
adev->irq.ih.doorbell_index);
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR,
|
||||
ENABLE, 1);
|
||||
} else {
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr, IH_DOORBELL_RPTR,
|
||||
ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
|
||||
IH_DOORBELL_RPTR,
|
||||
ENABLE, 0);
|
||||
}
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR, ih_doorbell_rtpr);
|
||||
adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
|
||||
adev->irq.ih.doorbell_index);
|
||||
|
||||
ih = &adev->irq.ih1;
|
||||
if (ih->ring_size) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
|
||||
(ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
|
||||
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
|
||||
}
|
||||
|
||||
ih = &adev->irq.ih2;
|
||||
if (ih->ring_size) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
|
||||
(ih->gpu_addr >> 40) & 0xff);
|
||||
|
||||
ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
|
||||
|
||||
/* set rptr, wptr to 0 */
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
|
||||
}
|
||||
|
||||
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
|
||||
tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
|
||||
|
@ -191,32 +267,58 @@ static void vega10_ih_irq_disable(struct amdgpu_device *adev)
|
|||
* ring buffer overflow and deal with it.
|
||||
* Returns the value of the wptr.
|
||||
*/
|
||||
static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
|
||||
static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
u32 wptr, tmp;
|
||||
u32 wptr, reg, tmp;
|
||||
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
wptr = le32_to_cpu(adev->irq.ih.ring[adev->irq.ih.wptr_offs]);
|
||||
wptr = le32_to_cpu(*ih->wptr_cpu);
|
||||
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
|
||||
/* Double check that the overflow wasn't already cleared. */
|
||||
|
||||
if (ih == &adev->irq.ih)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
|
||||
else if (ih == &adev->irq.ih1)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
|
||||
else if (ih == &adev->irq.ih2)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
|
||||
else
|
||||
wptr = le32_to_cpu(adev->wb.wb[adev->irq.ih.wptr_offs]);
|
||||
BUG();
|
||||
|
||||
if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
wptr = RREG32_NO_KIQ(reg);
|
||||
if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
|
||||
goto out;
|
||||
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 32). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
tmp = (wptr + 32) & adev->irq.ih.ptr_mask;
|
||||
dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, adev->irq.ih.rptr, tmp);
|
||||
adev->irq.ih.rptr = tmp;
|
||||
wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
|
||||
|
||||
tmp = RREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL));
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32_NO_KIQ(SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL), tmp);
|
||||
}
|
||||
return (wptr & adev->irq.ih.ptr_mask);
|
||||
/* When a ring buffer overflow happen start parsing interrupt
|
||||
* from the last not overwritten vector (wptr + 32). Hopefully
|
||||
* this should allow us to catchup.
|
||||
*/
|
||||
tmp = (wptr + 32) & ih->ptr_mask;
|
||||
dev_warn(adev->dev, "IH ring buffer overflow "
|
||||
"(0x%08X, 0x%08X, 0x%08X)\n",
|
||||
wptr, ih->rptr, tmp);
|
||||
ih->rptr = tmp;
|
||||
|
||||
if (ih == &adev->irq.ih)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
|
||||
else if (ih == &adev->irq.ih1)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
|
||||
else if (ih == &adev->irq.ih2)
|
||||
reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
|
||||
else
|
||||
BUG();
|
||||
|
||||
tmp = RREG32_NO_KIQ(reg);
|
||||
tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
|
||||
WREG32_NO_KIQ(reg, tmp);
|
||||
|
||||
out:
|
||||
return (wptr & ih->ptr_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,20 +330,21 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
|
|||
* position and also advance the position.
|
||||
*/
|
||||
static void vega10_ih_decode_iv(struct amdgpu_device *adev,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
struct amdgpu_ih_ring *ih,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
/* wptr/rptr are in bytes! */
|
||||
u32 ring_index = adev->irq.ih.rptr >> 2;
|
||||
u32 ring_index = ih->rptr >> 2;
|
||||
uint32_t dw[8];
|
||||
|
||||
dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
|
||||
dw[4] = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]);
|
||||
dw[5] = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]);
|
||||
dw[6] = le32_to_cpu(adev->irq.ih.ring[ring_index + 6]);
|
||||
dw[7] = le32_to_cpu(adev->irq.ih.ring[ring_index + 7]);
|
||||
dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
|
||||
dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
|
||||
dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
|
||||
dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
|
||||
dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
|
||||
dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
|
||||
dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
|
||||
dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
|
||||
|
||||
entry->client_id = dw[0] & 0xff;
|
||||
entry->src_id = (dw[0] >> 8) & 0xff;
|
||||
|
@ -257,9 +360,8 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
|
|||
entry->src_data[2] = dw[6];
|
||||
entry->src_data[3] = dw[7];
|
||||
|
||||
|
||||
/* wptr/rptr are in bytes! */
|
||||
adev->irq.ih.rptr += 32;
|
||||
ih->rptr += 32;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,37 +371,95 @@ static void vega10_ih_decode_iv(struct amdgpu_device *adev,
|
|||
*
|
||||
* Set the IH ring buffer rptr.
|
||||
*/
|
||||
static void vega10_ih_set_rptr(struct amdgpu_device *adev)
|
||||
static void vega10_ih_set_rptr(struct amdgpu_device *adev,
|
||||
struct amdgpu_ih_ring *ih)
|
||||
{
|
||||
if (adev->irq.ih.use_doorbell) {
|
||||
if (ih->use_doorbell) {
|
||||
/* XXX check if swapping is necessary on BE */
|
||||
if (adev->irq.ih.use_bus_addr)
|
||||
adev->irq.ih.ring[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
|
||||
else
|
||||
adev->wb.wb[adev->irq.ih.rptr_offs] = adev->irq.ih.rptr;
|
||||
WDOORBELL32(adev->irq.ih.doorbell_index, adev->irq.ih.rptr);
|
||||
} else {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, adev->irq.ih.rptr);
|
||||
*ih->rptr_cpu = ih->rptr;
|
||||
WDOORBELL32(ih->doorbell_index, ih->rptr);
|
||||
} else if (ih == &adev->irq.ih) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
|
||||
} else if (ih == &adev->irq.ih1) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
|
||||
} else if (ih == &adev->irq.ih2) {
|
||||
WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vega10_ih_self_irq - dispatch work for ring 1 and 2
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @source: irq source
|
||||
* @entry: IV with WPTR update
|
||||
*
|
||||
* Update the WPTR from the IV and schedule work to handle the entries.
|
||||
*/
|
||||
static int vega10_ih_self_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
uint32_t wptr = cpu_to_le32(entry->src_data[0]);
|
||||
|
||||
switch (entry->ring_id) {
|
||||
case 1:
|
||||
*adev->irq.ih1.wptr_cpu = wptr;
|
||||
schedule_work(&adev->irq.ih1_work);
|
||||
break;
|
||||
case 2:
|
||||
*adev->irq.ih2.wptr_cpu = wptr;
|
||||
schedule_work(&adev->irq.ih2_work);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
|
||||
.process = vega10_ih_self_irq,
|
||||
};
|
||||
|
||||
static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->irq.self_irq.num_types = 0;
|
||||
adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
|
||||
}
|
||||
|
||||
static int vega10_ih_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
vega10_ih_set_interrupt_funcs(adev);
|
||||
vega10_ih_set_self_irq_funcs(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vega10_ih_sw_init(void *handle)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
|
||||
&adev->irq.self_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (adev->asic_type == CHIP_VEGA10) {
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* TODO add doorbell for IH1 & IH2 as well */
|
||||
adev->irq.ih.use_doorbell = true;
|
||||
adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
|
||||
|
||||
|
@ -313,6 +473,8 @@ static int vega10_ih_sw_fini(void *handle)
|
|||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_fini(adev);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
|
||||
amdgpu_ih_ring_fini(adev, &adev->irq.ih);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -70,8 +70,8 @@ void vega10_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.userqueue_start = AMDGPU_DOORBELL64_USERQUEUE_START;
|
||||
adev->doorbell_index.userqueue_end = AMDGPU_DOORBELL64_USERQUEUE_END;
|
||||
adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL64_GFX_RING0;
|
||||
adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL64_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL64_sDMA_ENGINE1;
|
||||
adev->doorbell_index.sdma_engine[0] = AMDGPU_DOORBELL64_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine[1] = AMDGPU_DOORBELL64_sDMA_ENGINE1;
|
||||
adev->doorbell_index.ih = AMDGPU_DOORBELL64_IH;
|
||||
adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_DOORBELL64_UVD_RING0_1;
|
||||
adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_DOORBELL64_UVD_RING2_3;
|
||||
|
@ -83,5 +83,6 @@ void vega10_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_DOORBELL64_VCE_RING6_7;
|
||||
/* In unit of dword doorbell */
|
||||
adev->doorbell_index.max_assignment = AMDGPU_DOORBELL64_MAX_ASSIGNMENT << 1;
|
||||
adev->doorbell_index.sdma_doorbell_range = 4;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,14 @@ void vega20_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.userqueue_start = AMDGPU_VEGA20_DOORBELL_USERQUEUE_START;
|
||||
adev->doorbell_index.userqueue_end = AMDGPU_VEGA20_DOORBELL_USERQUEUE_END;
|
||||
adev->doorbell_index.gfx_ring0 = AMDGPU_VEGA20_DOORBELL_GFX_RING0;
|
||||
adev->doorbell_index.sdma_engine0 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine1 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1;
|
||||
adev->doorbell_index.sdma_engine2 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2;
|
||||
adev->doorbell_index.sdma_engine3 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3;
|
||||
adev->doorbell_index.sdma_engine4 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4;
|
||||
adev->doorbell_index.sdma_engine5 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5;
|
||||
adev->doorbell_index.sdma_engine6 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6;
|
||||
adev->doorbell_index.sdma_engine7 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7;
|
||||
adev->doorbell_index.sdma_engine[0] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine[1] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1;
|
||||
adev->doorbell_index.sdma_engine[2] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2;
|
||||
adev->doorbell_index.sdma_engine[3] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3;
|
||||
adev->doorbell_index.sdma_engine[4] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4;
|
||||
adev->doorbell_index.sdma_engine[5] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5;
|
||||
adev->doorbell_index.sdma_engine[6] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6;
|
||||
adev->doorbell_index.sdma_engine[7] = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7;
|
||||
adev->doorbell_index.ih = AMDGPU_VEGA20_DOORBELL_IH;
|
||||
adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_VEGA20_DOORBELL64_UVD_RING0_1;
|
||||
adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_VEGA20_DOORBELL64_UVD_RING2_3;
|
||||
|
@ -86,5 +86,6 @@ void vega20_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.uvd_vce.vce_ring4_5 = AMDGPU_VEGA20_DOORBELL64_VCE_RING4_5;
|
||||
adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_VEGA20_DOORBELL64_VCE_RING6_7;
|
||||
adev->doorbell_index.max_assignment = AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT << 1;
|
||||
adev->doorbell_index.sdma_doorbell_range = 20;
|
||||
}
|
||||
|
||||
|
|
|
@ -941,6 +941,69 @@ static bool vi_need_full_reset(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
static void vi_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
|
||||
uint64_t *count1)
|
||||
{
|
||||
uint32_t perfctr = 0;
|
||||
uint64_t cnt0_of, cnt1_of;
|
||||
int tmp;
|
||||
|
||||
/* This reports 0 on APUs, so return to avoid writing/reading registers
|
||||
* that may or may not be different from their GPU counterparts
|
||||
*/
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return;
|
||||
|
||||
/* Set the 2 events that we wish to watch, defined above */
|
||||
/* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
|
||||
perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
|
||||
|
||||
/* Write to enable desired perf counters */
|
||||
WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
|
||||
/* Zero out and enable the perf counters
|
||||
* Write 0x5:
|
||||
* Bit 0 = Start all counters(1)
|
||||
* Bit 2 = Global counter reset enable(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
|
||||
|
||||
msleep(1000);
|
||||
|
||||
/* Load the shadow and disable the perf counters
|
||||
* Write 0x2:
|
||||
* Bit 0 = Stop counters(0)
|
||||
* Bit 1 = Load the shadow counters(1)
|
||||
*/
|
||||
WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
|
||||
|
||||
/* Read register values to get any >32bit overflow */
|
||||
tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
|
||||
cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
|
||||
cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
|
||||
|
||||
/* Get the values and add the overflow */
|
||||
*count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
|
||||
*count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
|
||||
}
|
||||
|
||||
static bool vi_need_reset_on_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 clock_cntl, pc;
|
||||
|
||||
if (adev->flags & AMD_IS_APU)
|
||||
return false;
|
||||
|
||||
/* check if the SMC is already running */
|
||||
clock_cntl = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
|
||||
pc = RREG32_SMC(ixSMC_PC_C);
|
||||
if ((0 == REG_GET_FIELD(clock_cntl, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) &&
|
||||
(0x20100 <= pc))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct amdgpu_asic_funcs vi_asic_funcs =
|
||||
{
|
||||
.read_disabled_bios = &vi_read_disabled_bios,
|
||||
|
@ -956,6 +1019,8 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
|
|||
.invalidate_hdp = &vi_invalidate_hdp,
|
||||
.need_full_reset = &vi_need_full_reset,
|
||||
.init_doorbell_index = &legacy_doorbell_index_init,
|
||||
.get_pcie_usage = &vi_get_pcie_usage,
|
||||
.need_reset_on_init = &vi_need_reset_on_init,
|
||||
};
|
||||
|
||||
#define CZ_REV_BRISTOL(rev) \
|
||||
|
@ -1726,8 +1791,8 @@ void legacy_doorbell_index_init(struct amdgpu_device *adev)
|
|||
adev->doorbell_index.mec_ring6 = AMDGPU_DOORBELL_MEC_RING6;
|
||||
adev->doorbell_index.mec_ring7 = AMDGPU_DOORBELL_MEC_RING7;
|
||||
adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL_GFX_RING0;
|
||||
adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL_sDMA_ENGINE1;
|
||||
adev->doorbell_index.sdma_engine[0] = AMDGPU_DOORBELL_sDMA_ENGINE0;
|
||||
adev->doorbell_index.sdma_engine[1] = AMDGPU_DOORBELL_sDMA_ENGINE1;
|
||||
adev->doorbell_index.ih = AMDGPU_DOORBELL_IH;
|
||||
adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_MAX_ASSIGNMENT;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
config HSA_AMD
|
||||
bool "HSA kernel driver for AMD GPU devices"
|
||||
depends on DRM_AMDGPU && X86_64
|
||||
imply AMD_IOMMU_V2
|
||||
depends on DRM_AMDGPU && (X86_64 || ARM64)
|
||||
imply AMD_IOMMU_V2 if X86_64
|
||||
select MMU_NOTIFIER
|
||||
help
|
||||
Enable this if you want to use HSA features on AMD GPU devices.
|
||||
|
|
|
@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_X86_64
|
||||
static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
|
||||
uint32_t *num_entries,
|
||||
struct crat_subtype_iolink *sub_type_hdr)
|
||||
|
@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
|
||||
*
|
||||
|
@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
|
|||
struct crat_subtype_generic *sub_type_hdr;
|
||||
int avail_size = *size;
|
||||
int numa_node_id;
|
||||
#ifdef CONFIG_X86_64
|
||||
uint32_t entries = 0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
|
||||
|
@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
|
|||
sub_type_hdr->length);
|
||||
|
||||
/* Fill in Subtype: IO Link */
|
||||
#ifdef CONFIG_X86_64
|
||||
ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
|
||||
&entries,
|
||||
(struct crat_subtype_iolink *)sub_type_hdr);
|
||||
|
@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
|
|||
|
||||
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
|
||||
sub_type_hdr->length * entries);
|
||||
#else
|
||||
pr_info("IO link not available for non x86 platforms\n");
|
||||
#endif
|
||||
|
||||
crat_table->num_domains++;
|
||||
}
|
||||
|
|
|
@ -23,22 +23,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/device.h>
|
||||
#include "kfd_priv.h"
|
||||
|
||||
static const struct kgd2kfd_calls kgd2kfd = {
|
||||
.exit = kgd2kfd_exit,
|
||||
.probe = kgd2kfd_probe,
|
||||
.device_init = kgd2kfd_device_init,
|
||||
.device_exit = kgd2kfd_device_exit,
|
||||
.interrupt = kgd2kfd_interrupt,
|
||||
.suspend = kgd2kfd_suspend,
|
||||
.resume = kgd2kfd_resume,
|
||||
.quiesce_mm = kgd2kfd_quiesce_mm,
|
||||
.resume_mm = kgd2kfd_resume_mm,
|
||||
.schedule_evict_and_restore_process =
|
||||
kgd2kfd_schedule_evict_and_restore_process,
|
||||
.pre_reset = kgd2kfd_pre_reset,
|
||||
.post_reset = kgd2kfd_post_reset,
|
||||
};
|
||||
#include "amdgpu_amdkfd.h"
|
||||
|
||||
static int kfd_init(void)
|
||||
{
|
||||
|
@ -91,20 +76,10 @@ static void kfd_exit(void)
|
|||
kfd_chardev_exit();
|
||||
}
|
||||
|
||||
int kgd2kfd_init(unsigned int interface_version,
|
||||
const struct kgd2kfd_calls **g2f)
|
||||
int kgd2kfd_init()
|
||||
{
|
||||
int err;
|
||||
|
||||
err = kfd_init();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*g2f = &kgd2kfd;
|
||||
|
||||
return 0;
|
||||
return kfd_init();
|
||||
}
|
||||
EXPORT_SYMBOL(kgd2kfd_init);
|
||||
|
||||
void kgd2kfd_exit(void)
|
||||
{
|
||||
|
|
|
@ -266,14 +266,6 @@ struct kfd_dev {
|
|||
bool pci_atomic_requested;
|
||||
};
|
||||
|
||||
/* KGD2KFD callbacks */
|
||||
void kgd2kfd_exit(void);
|
||||
struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,
|
||||
struct pci_dev *pdev, const struct kfd2kgd_calls *f2g);
|
||||
bool kgd2kfd_device_init(struct kfd_dev *kfd,
|
||||
const struct kgd2kfd_shared_resources *gpu_resources);
|
||||
void kgd2kfd_device_exit(struct kfd_dev *kfd);
|
||||
|
||||
enum kfd_mempool {
|
||||
KFD_MEMPOOL_SYSTEM_CACHEABLE = 1,
|
||||
KFD_MEMPOOL_SYSTEM_WRITECOMBINE = 2,
|
||||
|
@ -541,11 +533,6 @@ struct qcm_process_device {
|
|||
/* Approx. time before evicting the process again */
|
||||
#define PROCESS_ACTIVE_TIME_MS 10
|
||||
|
||||
int kgd2kfd_quiesce_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_resume_mm(struct mm_struct *mm);
|
||||
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
|
||||
struct dma_fence *fence);
|
||||
|
||||
/* 8 byte handle containing GPU ID in the most significant 4 bytes and
|
||||
* idr_handle in the least significant 4 bytes
|
||||
*/
|
||||
|
@ -800,20 +787,11 @@ int kfd_numa_node_to_apic_id(int numa_node_id);
|
|||
/* Interrupts */
|
||||
int kfd_interrupt_init(struct kfd_dev *dev);
|
||||
void kfd_interrupt_exit(struct kfd_dev *dev);
|
||||
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry);
|
||||
bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry);
|
||||
bool interrupt_is_wanted(struct kfd_dev *dev,
|
||||
const uint32_t *ih_ring_entry,
|
||||
uint32_t *patched_ihre, bool *flag);
|
||||
|
||||
/* Power Management */
|
||||
void kgd2kfd_suspend(struct kfd_dev *kfd);
|
||||
int kgd2kfd_resume(struct kfd_dev *kfd);
|
||||
|
||||
/* GPU reset */
|
||||
int kgd2kfd_pre_reset(struct kfd_dev *kfd);
|
||||
int kgd2kfd_post_reset(struct kfd_dev *kfd);
|
||||
|
||||
/* amdkfd Apertures */
|
||||
int kfd_init_apertures(struct kfd_process *process);
|
||||
|
||||
|
|
|
@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
|
|||
* the GPU device is not already present in the topology device
|
||||
* list then return NULL. This means a new topology device has to
|
||||
* be created for this GPU.
|
||||
* TODO: Rather than assiging @gpu to first topology device withtout
|
||||
* gpu attached, it will better to have more stringent check.
|
||||
*/
|
||||
static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
|
||||
{
|
||||
|
@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
|
|||
struct kfd_topology_device *out_dev = NULL;
|
||||
|
||||
down_write(&topology_lock);
|
||||
list_for_each_entry(dev, &topology_device_list, list)
|
||||
list_for_each_entry(dev, &topology_device_list, list) {
|
||||
/* Discrete GPUs need their own topology device list
|
||||
* entries. Don't assign them to CPU/APU nodes.
|
||||
*/
|
||||
if (!gpu->device_info->needs_iommu_device &&
|
||||
dev->node_props.cpu_cores_count)
|
||||
continue;
|
||||
|
||||
if (!dev->gpu && (dev->node_props.simd_count > 0)) {
|
||||
dev->gpu = gpu;
|
||||
out_dev = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_write(&topology_lock);
|
||||
return out_dev;
|
||||
}
|
||||
|
@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
|
|||
|
||||
static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
|
||||
{
|
||||
const struct cpuinfo_x86 *cpuinfo;
|
||||
int first_cpu_of_numa_node;
|
||||
|
||||
if (!cpumask || cpumask == cpu_none_mask)
|
||||
|
@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
|
|||
first_cpu_of_numa_node = cpumask_first(cpumask);
|
||||
if (first_cpu_of_numa_node >= nr_cpu_ids)
|
||||
return -1;
|
||||
cpuinfo = &cpu_data(first_cpu_of_numa_node);
|
||||
|
||||
return cpuinfo->apicid;
|
||||
#ifdef CONFIG_X86_64
|
||||
return cpu_data(first_cpu_of_numa_node).apicid;
|
||||
#else
|
||||
return first_cpu_of_numa_node;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -783,6 +783,45 @@ static ssize_t dtn_log_write(
|
|||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backlight at this moment. Read only.
|
||||
* As written to display, taking ABM and backlight lut into account.
|
||||
* Ranges from 0x0 to 0x10000 (= 100% PWM)
|
||||
*/
|
||||
static int current_backlight_read(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
unsigned int backlight = dc_get_current_backlight_pwm(dc);
|
||||
|
||||
seq_printf(m, "0x%x\n", backlight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backlight value that is being approached. Read only.
|
||||
* As written to display, taking ABM and backlight lut into account.
|
||||
* Ranges from 0x0 to 0x10000 (= 100% PWM)
|
||||
*/
|
||||
static int target_backlight_read(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
unsigned int backlight = dc_get_target_backlight_pwm(dc);
|
||||
|
||||
seq_printf(m, "0x%x\n", backlight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
|
||||
{"amdgpu_current_backlight_pwm", ¤t_backlight_read},
|
||||
{"amdgpu_target_backlight_pwm", &target_backlight_read},
|
||||
};
|
||||
|
||||
int dtn_debugfs_init(struct amdgpu_device *adev)
|
||||
{
|
||||
static const struct file_operations dtn_log_fops = {
|
||||
|
@ -793,9 +832,15 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
|
|||
};
|
||||
|
||||
struct drm_minor *minor = adev->ddev->primary;
|
||||
struct dentry *root = minor->debugfs_root;
|
||||
struct dentry *ent, *root = minor->debugfs_root;
|
||||
int ret;
|
||||
|
||||
struct dentry *ent = debugfs_create_file(
|
||||
ret = amdgpu_debugfs_add_files(adev, amdgpu_dm_debugfs_list,
|
||||
ARRAY_SIZE(amdgpu_dm_debugfs_list));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ent = debugfs_create_file(
|
||||
"amdgpu_dm_dtn_log",
|
||||
0644,
|
||||
root,
|
||||
|
|
|
@ -192,7 +192,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
|||
int bpp = 0;
|
||||
int pbn = 0;
|
||||
|
||||
aconnector = stream->sink->priv;
|
||||
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
@ -205,7 +205,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
|
|||
mst_port = aconnector->port;
|
||||
|
||||
if (enable) {
|
||||
clock = stream->timing.pix_clk_khz;
|
||||
clock = stream->timing.pix_clk_100hz / 10;
|
||||
|
||||
switch (stream->timing.display_color_depth) {
|
||||
|
||||
|
@ -284,7 +284,7 @@ bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
|||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
int ret;
|
||||
|
||||
aconnector = stream->sink->priv;
|
||||
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
@ -312,7 +312,7 @@ bool dm_helpers_dp_mst_send_payload_allocation(
|
|||
struct drm_dp_mst_port *mst_port;
|
||||
int ret;
|
||||
|
||||
aconnector = stream->sink->priv;
|
||||
aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include "dc_link_ddc.h"
|
||||
|
||||
#include "i2caux_interface.h"
|
||||
|
||||
/* #define TRACE_DPCD */
|
||||
|
||||
#ifdef TRACE_DPCD
|
||||
|
@ -81,80 +83,24 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
|||
struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
ssize_t result = 0;
|
||||
enum i2caux_transaction_action action;
|
||||
enum aux_transaction_type type;
|
||||
struct aux_payload payload;
|
||||
|
||||
if (WARN_ON(msg->size > 16))
|
||||
return -E2BIG;
|
||||
|
||||
switch (msg->request & ~DP_AUX_I2C_MOT) {
|
||||
case DP_AUX_NATIVE_READ:
|
||||
type = AUX_TRANSACTION_TYPE_DP;
|
||||
action = I2CAUX_TRANSACTION_ACTION_DP_READ;
|
||||
payload.address = msg->address;
|
||||
payload.data = msg->buffer;
|
||||
payload.length = msg->size;
|
||||
payload.reply = &msg->reply;
|
||||
payload.i2c_over_aux = (msg->request & DP_AUX_NATIVE_WRITE) == 0;
|
||||
payload.write = (msg->request & DP_AUX_I2C_READ) == 0;
|
||||
payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0;
|
||||
payload.defer_delay = 0;
|
||||
|
||||
result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
|
||||
msg->address,
|
||||
&msg->reply,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
type,
|
||||
action);
|
||||
break;
|
||||
case DP_AUX_NATIVE_WRITE:
|
||||
type = AUX_TRANSACTION_TYPE_DP;
|
||||
action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
|
||||
result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, &payload);
|
||||
|
||||
dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
|
||||
msg->address,
|
||||
&msg->reply,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
type,
|
||||
action);
|
||||
if (payload.write)
|
||||
result = msg->size;
|
||||
break;
|
||||
case DP_AUX_I2C_READ:
|
||||
type = AUX_TRANSACTION_TYPE_I2C;
|
||||
if (msg->request & DP_AUX_I2C_MOT)
|
||||
action = I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
|
||||
else
|
||||
action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
|
||||
|
||||
result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
|
||||
msg->address,
|
||||
&msg->reply,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
type,
|
||||
action);
|
||||
break;
|
||||
case DP_AUX_I2C_WRITE:
|
||||
type = AUX_TRANSACTION_TYPE_I2C;
|
||||
if (msg->request & DP_AUX_I2C_MOT)
|
||||
action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
|
||||
else
|
||||
action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
|
||||
|
||||
dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service,
|
||||
msg->address,
|
||||
&msg->reply,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
type,
|
||||
action);
|
||||
result = msg->size;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef TRACE_DPCD
|
||||
log_dpcd(msg->request,
|
||||
msg->address,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
r == DDC_RESULT_SUCESSFULL);
|
||||
#endif
|
||||
|
||||
if (result < 0) /* DC doesn't know about kernel error codes */
|
||||
result = -EIO;
|
||||
|
|
|
@ -559,6 +559,58 @@ void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
|
|||
pp_funcs->notify_smu_enable_pwe(pp_handle);
|
||||
}
|
||||
|
||||
void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
|
||||
{
|
||||
const struct dc_context *ctx = pp->dm;
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs || !pp_funcs->set_active_display_count)
|
||||
return;
|
||||
|
||||
pp_funcs->set_active_display_count(pp_handle, count);
|
||||
}
|
||||
|
||||
void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
|
||||
{
|
||||
const struct dc_context *ctx = pp->dm;
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
|
||||
return;
|
||||
|
||||
pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock);
|
||||
}
|
||||
|
||||
void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
|
||||
{
|
||||
const struct dc_context *ctx = pp->dm;
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq)
|
||||
return;
|
||||
|
||||
pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock);
|
||||
}
|
||||
|
||||
void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
|
||||
{
|
||||
const struct dc_context *ctx = pp->dm;
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
|
||||
if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq)
|
||||
return;
|
||||
|
||||
pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz);
|
||||
}
|
||||
|
||||
void dm_pp_get_funcs_rv(
|
||||
struct dc_context *ctx,
|
||||
struct pp_smu_funcs_rv *funcs)
|
||||
|
@ -567,4 +619,9 @@ void dm_pp_get_funcs_rv(
|
|||
funcs->set_display_requirement = pp_rv_set_display_requirement;
|
||||
funcs->set_wm_ranges = pp_rv_set_wm_ranges;
|
||||
funcs->set_pme_wa_enable = pp_rv_set_pme_wa_enable;
|
||||
funcs->set_display_count = pp_rv_set_active_display_count;
|
||||
funcs->set_min_deep_sleep_dcfclk = pp_rv_set_min_deep_sleep_dcfclk;
|
||||
funcs->set_hard_min_dcfclk_by_freq = pp_rv_set_hard_min_dcefclk_by_freq;
|
||||
funcs->set_hard_min_fclk_by_freq = pp_rv_set_hard_min_fclk_by_freq;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
# Makefile for Display Core (dc) component.
|
||||
#
|
||||
|
||||
DC_LIBS = basics bios calcs dce gpio i2caux irq virtual
|
||||
DC_LIBS = basics bios calcs dce gpio irq virtual
|
||||
|
||||
ifdef CONFIG_DRM_AMD_DC_DCN1_0
|
||||
DC_LIBS += dcn10 dml
|
||||
|
@ -41,7 +41,8 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI
|
|||
include $(AMD_DC)
|
||||
|
||||
DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
|
||||
dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o
|
||||
dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \
|
||||
dc_vm_helper.o
|
||||
|
||||
AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
|
||||
|
||||
|
|
|
@ -835,18 +835,6 @@ static enum bp_result bios_parser_enable_crtc(
|
|||
return bp->cmd_tbl.enable_crtc(bp, id, enable);
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_crtc_source_select(
|
||||
struct dc_bios *dcb,
|
||||
struct bp_crtc_source_select *bp_params)
|
||||
{
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
|
||||
if (!bp->cmd_tbl.select_crtc_source)
|
||||
return BP_RESULT_FAILURE;
|
||||
|
||||
return bp->cmd_tbl.select_crtc_source(bp, bp_params);
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_enable_disp_power_gating(
|
||||
struct dc_bios *dcb,
|
||||
enum controller_id controller_id,
|
||||
|
@ -2842,8 +2830,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
|
|||
|
||||
.program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */
|
||||
|
||||
.crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */
|
||||
|
||||
.program_display_engine_pll = bios_parser_program_display_engine_pll,
|
||||
|
||||
.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
|
||||
|
|
|
@ -1083,18 +1083,6 @@ static enum bp_result bios_parser_enable_crtc(
|
|||
return bp->cmd_tbl.enable_crtc(bp, id, enable);
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_crtc_source_select(
|
||||
struct dc_bios *dcb,
|
||||
struct bp_crtc_source_select *bp_params)
|
||||
{
|
||||
struct bios_parser *bp = BP_FROM_DCB(dcb);
|
||||
|
||||
if (!bp->cmd_tbl.select_crtc_source)
|
||||
return BP_RESULT_FAILURE;
|
||||
|
||||
return bp->cmd_tbl.select_crtc_source(bp, bp_params);
|
||||
}
|
||||
|
||||
static enum bp_result bios_parser_enable_disp_power_gating(
|
||||
struct dc_bios *dcb,
|
||||
enum controller_id controller_id,
|
||||
|
@ -1899,8 +1887,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
|
|||
|
||||
.is_accelerated_mode = bios_parser_is_accelerated_mode,
|
||||
|
||||
.is_active_display = bios_is_active_display,
|
||||
|
||||
.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
|
||||
|
||||
|
||||
|
@ -1917,8 +1903,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
|
|||
|
||||
.program_crtc_timing = bios_parser_program_crtc_timing,
|
||||
|
||||
.crtc_source_select = bios_parser_crtc_source_select,
|
||||
|
||||
.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
|
||||
|
||||
.bios_parser_destroy = firmware_parser_destroy,
|
||||
|
|
|
@ -83,101 +83,7 @@ uint32_t bios_get_vga_enabled_displays(
|
|||
{
|
||||
uint32_t active_disp = 1;
|
||||
|
||||
if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/
|
||||
active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF;
|
||||
active_disp = REG_READ(BIOS_SCRATCH_3) & 0XFFFF;
|
||||
return active_disp;
|
||||
}
|
||||
|
||||
bool bios_is_active_display(
|
||||
struct dc_bios *bios,
|
||||
enum signal_type signal,
|
||||
const struct connector_device_tag_info *device_tag)
|
||||
{
|
||||
uint32_t active = 0;
|
||||
uint32_t connected = 0;
|
||||
uint32_t bios_scratch_0 = 0;
|
||||
uint32_t bios_scratch_3 = 0;
|
||||
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
{
|
||||
if (device_tag->dev_id.device_type == DEVICE_TYPE_DFP) {
|
||||
switch (device_tag->dev_id.enum_id) {
|
||||
case 1:
|
||||
{
|
||||
active = ATOM_S3_DFP1_ACTIVE;
|
||||
connected = 0x0008; //ATOM_DISPLAY_DFP1_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
active = ATOM_S3_DFP2_ACTIVE;
|
||||
connected = 0x0080; //ATOM_DISPLAY_DFP2_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
active = ATOM_S3_DFP3_ACTIVE;
|
||||
connected = 0x0200; //ATOM_DISPLAY_DFP3_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
active = ATOM_S3_DFP4_ACTIVE;
|
||||
connected = 0x0400; //ATOM_DISPLAY_DFP4_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
{
|
||||
active = ATOM_S3_DFP5_ACTIVE;
|
||||
connected = 0x0800; //ATOM_DISPLAY_DFP5_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
{
|
||||
active = ATOM_S3_DFP6_ACTIVE;
|
||||
connected = 0x0040; //ATOM_DISPLAY_DFP6_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGNAL_TYPE_LVDS:
|
||||
case SIGNAL_TYPE_EDP:
|
||||
{
|
||||
active = ATOM_S3_LCD1_ACTIVE;
|
||||
connected = 0x0002; //ATOM_DISPLAY_LCD1_CONNECT
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (bios->regs->BIOS_SCRATCH_0) /*follow up with other asic, todo*/
|
||||
bios_scratch_0 = REG_READ(BIOS_SCRATCH_0);
|
||||
if (bios->regs->BIOS_SCRATCH_3) /*follow up with other asic, todo*/
|
||||
bios_scratch_3 = REG_READ(BIOS_SCRATCH_3);
|
||||
|
||||
bios_scratch_3 &= ATOM_S3_DEVICE_ACTIVE_MASK;
|
||||
if ((active & bios_scratch_3) && (connected & bios_scratch_0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,6 @@ bool bios_is_accelerated_mode(struct dc_bios *bios);
|
|||
void bios_set_scratch_acc_mode_change(struct dc_bios *bios);
|
||||
void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
|
||||
uint32_t bios_get_vga_enabled_displays(struct dc_bios *bios);
|
||||
bool bios_is_active_display(
|
||||
struct dc_bios *bios,
|
||||
enum signal_type signal,
|
||||
const struct connector_device_tag_info *device_tag);
|
||||
|
||||
#define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type)))
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ static void init_adjust_display_pll(struct bios_parser *bp);
|
|||
static void init_dac_encoder_control(struct bios_parser *bp);
|
||||
static void init_dac_output_control(struct bios_parser *bp);
|
||||
static void init_set_crtc_timing(struct bios_parser *bp);
|
||||
static void init_select_crtc_source(struct bios_parser *bp);
|
||||
static void init_enable_crtc(struct bios_parser *bp);
|
||||
static void init_enable_crtc_mem_req(struct bios_parser *bp);
|
||||
static void init_external_encoder_control(struct bios_parser *bp);
|
||||
|
@ -73,7 +72,6 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
|
|||
init_dac_encoder_control(bp);
|
||||
init_dac_output_control(bp);
|
||||
init_set_crtc_timing(bp);
|
||||
init_select_crtc_source(bp);
|
||||
init_enable_crtc(bp);
|
||||
init_enable_crtc_mem_req(bp);
|
||||
init_program_clock(bp);
|
||||
|
@ -964,9 +962,9 @@ static enum bp_result set_pixel_clock_v3(
|
|||
allocation.sPCLKInput.ucPostDiv =
|
||||
(uint8_t)bp_params->pixel_clock_post_divider;
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
/* We need to convert from 100Hz units into 10KHz units */
|
||||
allocation.sPCLKInput.usPixelClock =
|
||||
cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
|
||||
cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
|
||||
|
||||
params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
|
||||
params->ucTransmitterId =
|
||||
|
@ -1042,9 +1040,9 @@ static enum bp_result set_pixel_clock_v5(
|
|||
(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
|
||||
bp_params->signal_type, false);
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
/* We need to convert from 100Hz units into 10KHz units */
|
||||
clk.sPCLKInput.usPixelClock =
|
||||
cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
|
||||
cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
|
||||
|
||||
if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
|
||||
clk.sPCLKInput.ucMiscInfo |=
|
||||
|
@ -1118,9 +1116,9 @@ static enum bp_result set_pixel_clock_v6(
|
|||
(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
|
||||
bp_params->signal_type, false);
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
/* We need to convert from 100 Hz units into 10KHz units */
|
||||
clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
|
||||
cpu_to_le32(bp_params->target_pixel_clock / 10);
|
||||
cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
|
||||
|
||||
if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
|
||||
clk.sPCLKInput.ucMiscInfo |=
|
||||
|
@ -1182,8 +1180,7 @@ static enum bp_result set_pixel_clock_v7(
|
|||
clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
|
||||
clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
|
||||
clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
|
||||
|
||||
clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
|
||||
|
||||
|
@ -1896,120 +1893,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3(
|
|||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************************************************************************
|
||||
**
|
||||
** SELECT CRTC SOURCE
|
||||
**
|
||||
********************************************************************************
|
||||
*******************************************************************************/
|
||||
|
||||
static enum bp_result select_crtc_source_v2(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
static enum bp_result select_crtc_source_v3(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
|
||||
static void init_select_crtc_source(struct bios_parser *bp)
|
||||
{
|
||||
switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
|
||||
case 2:
|
||||
bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
|
||||
break;
|
||||
case 3:
|
||||
bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
|
||||
break;
|
||||
default:
|
||||
dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
|
||||
BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source));
|
||||
bp->cmd_tbl.select_crtc_source = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static enum bp_result select_crtc_source_v2(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params)
|
||||
{
|
||||
enum bp_result result = BP_RESULT_FAILURE;
|
||||
SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
|
||||
uint8_t atom_controller_id;
|
||||
uint32_t atom_engine_id;
|
||||
enum signal_type s = bp_params->signal;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
/* set controller id */
|
||||
if (bp->cmd_helper->controller_id_to_atom(
|
||||
bp_params->controller_id, &atom_controller_id))
|
||||
params.ucCRTC = atom_controller_id;
|
||||
else
|
||||
return BP_RESULT_FAILURE;
|
||||
|
||||
/* set encoder id */
|
||||
if (bp->cmd_helper->engine_bp_to_atom(
|
||||
bp_params->engine_id, &atom_engine_id))
|
||||
params.ucEncoderID = (uint8_t)atom_engine_id;
|
||||
else
|
||||
return BP_RESULT_FAILURE;
|
||||
|
||||
if (SIGNAL_TYPE_EDP == s ||
|
||||
(SIGNAL_TYPE_DISPLAY_PORT == s &&
|
||||
SIGNAL_TYPE_LVDS == bp_params->sink_signal))
|
||||
s = SIGNAL_TYPE_LVDS;
|
||||
|
||||
params.ucEncodeMode =
|
||||
(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
|
||||
s, bp_params->enable_dp_audio);
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
|
||||
result = BP_RESULT_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum bp_result select_crtc_source_v3(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params)
|
||||
{
|
||||
bool result = BP_RESULT_FAILURE;
|
||||
SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
|
||||
uint8_t atom_controller_id;
|
||||
uint32_t atom_engine_id;
|
||||
enum signal_type s = bp_params->signal;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
|
||||
&atom_controller_id))
|
||||
params.ucCRTC = atom_controller_id;
|
||||
else
|
||||
return result;
|
||||
|
||||
if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
|
||||
&atom_engine_id))
|
||||
params.ucEncoderID = (uint8_t)atom_engine_id;
|
||||
else
|
||||
return result;
|
||||
|
||||
if (SIGNAL_TYPE_EDP == s ||
|
||||
(SIGNAL_TYPE_DISPLAY_PORT == s &&
|
||||
SIGNAL_TYPE_LVDS == bp_params->sink_signal))
|
||||
s = SIGNAL_TYPE_LVDS;
|
||||
|
||||
params.ucEncodeMode =
|
||||
bp->cmd_helper->encoder_mode_bp_to_atom(
|
||||
s, bp_params->enable_dp_audio);
|
||||
/* Needed for VBIOS Random Spatial Dithering feature */
|
||||
params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
|
||||
result = BP_RESULT_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
********************************************************************************
|
||||
**
|
||||
|
@ -2164,7 +2047,7 @@ static enum bp_result program_clock_v5(
|
|||
/* We need to convert from KHz units into 10KHz units */
|
||||
params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
|
||||
params.sPCLKInput.usPixelClock =
|
||||
cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
|
||||
cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
|
||||
params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
|
||||
|
||||
if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
|
||||
|
@ -2196,7 +2079,7 @@ static enum bp_result program_clock_v6(
|
|||
/* We need to convert from KHz units into 10KHz units */
|
||||
params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
|
||||
params.sPCLKInput.ulDispEngClkFreq =
|
||||
cpu_to_le32(bp_params->target_pixel_clock / 10);
|
||||
cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
|
||||
|
||||
if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
|
||||
params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
|
||||
|
|
|
@ -71,9 +71,6 @@ struct cmd_tbl {
|
|||
enum bp_result (*set_crtc_timing)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_hw_crtc_timing_parameters *bp_params);
|
||||
enum bp_result (*select_crtc_source)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
enum bp_result (*enable_crtc)(
|
||||
struct bios_parser *bp,
|
||||
enum controller_id controller_id,
|
||||
|
|
|
@ -301,17 +301,17 @@ static enum bp_result set_pixel_clock_v7(
|
|||
cmd_helper->encoder_mode_bp_to_atom(
|
||||
bp_params->signal_type, false);
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock *
|
||||
10);
|
||||
clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock_100hz);
|
||||
|
||||
clk.deep_color_ratio =
|
||||
(uint8_t) bp->cmd_helper->
|
||||
transmitter_color_depth_to_atom(
|
||||
bp_params->color_depth);
|
||||
DC_LOG_BIOS("%s:program display clock = %d"\
|
||||
"colorDepth = %d\n", __func__,\
|
||||
bp_params->target_pixel_clock, bp_params->color_depth);
|
||||
|
||||
DC_LOG_BIOS("%s:program display clock = %d, tg = %d, pll = %d, "\
|
||||
"colorDepth = %d\n", __func__,
|
||||
bp_params->target_pixel_clock_100hz, (int)controller_id,
|
||||
pll_id, bp_params->color_depth);
|
||||
|
||||
if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
|
||||
clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
|
||||
|
@ -460,75 +460,6 @@ static enum bp_result set_crtc_using_dtd_timing_v3(
|
|||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
**
|
||||
** SELECT CRTC SOURCE
|
||||
**
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
static enum bp_result select_crtc_source_v3(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
|
||||
static void init_select_crtc_source(struct bios_parser *bp)
|
||||
{
|
||||
switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) {
|
||||
case 3:
|
||||
bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
|
||||
break;
|
||||
default:
|
||||
dm_output_to_console("Don't select_crtc_source enable_crtc for v%d\n",
|
||||
BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source));
|
||||
bp->cmd_tbl.select_crtc_source = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum bp_result select_crtc_source_v3(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params)
|
||||
{
|
||||
bool result = BP_RESULT_FAILURE;
|
||||
struct select_crtc_source_parameters_v2_3 params;
|
||||
uint8_t atom_controller_id;
|
||||
uint32_t atom_engine_id;
|
||||
enum signal_type s = bp_params->signal;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
|
||||
&atom_controller_id))
|
||||
params.crtc_id = atom_controller_id;
|
||||
else
|
||||
return result;
|
||||
|
||||
if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
|
||||
&atom_engine_id))
|
||||
params.encoder_id = (uint8_t)atom_engine_id;
|
||||
else
|
||||
return result;
|
||||
|
||||
if (s == SIGNAL_TYPE_EDP ||
|
||||
(s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal ==
|
||||
SIGNAL_TYPE_LVDS))
|
||||
s = SIGNAL_TYPE_LVDS;
|
||||
|
||||
params.encode_mode =
|
||||
bp->cmd_helper->encoder_mode_bp_to_atom(
|
||||
s, bp_params->enable_dp_audio);
|
||||
/* Needed for VBIOS Random Spatial Dithering feature */
|
||||
params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth);
|
||||
|
||||
if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params))
|
||||
result = BP_RESULT_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
**
|
||||
|
@ -808,7 +739,6 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)
|
|||
|
||||
init_set_crtc_timing(bp);
|
||||
|
||||
init_select_crtc_source(bp);
|
||||
init_enable_crtc(bp);
|
||||
|
||||
init_external_encoder_control(bp);
|
||||
|
|
|
@ -71,9 +71,6 @@ struct cmd_tbl {
|
|||
enum bp_result (*set_crtc_timing)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_hw_crtc_timing_parameters *bp_params);
|
||||
enum bp_result (*select_crtc_source)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
enum bp_result (*enable_crtc)(
|
||||
struct bios_parser *bp,
|
||||
enum controller_id controller_id,
|
||||
|
|
|
@ -30,7 +30,7 @@ else ifneq ($(call cc-option, -mstack-alignment=16),)
|
|||
cc_stack_align := -mstack-alignment=16
|
||||
endif
|
||||
|
||||
calcs_ccflags := -mhard-float -msse $(cc_stack_align)
|
||||
calcs_ccflags := -mhard-float -msse -msse2 $(cc_stack_align)
|
||||
|
||||
CFLAGS_dcn_calcs.o := $(calcs_ccflags)
|
||||
CFLAGS_dcn_calc_auto.o := $(calcs_ccflags)
|
||||
|
|
|
@ -2792,7 +2792,7 @@ static void populate_initial_data(
|
|||
data->lpt_en[num_displays + 4] = false;
|
||||
data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total);
|
||||
data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total);
|
||||
data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_khz, 1000);
|
||||
data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pipe[i].stream->timing.pix_clk_100hz, 10000);
|
||||
data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width);
|
||||
data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4];
|
||||
data->src_height[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.height);
|
||||
|
@ -2881,7 +2881,7 @@ static void populate_initial_data(
|
|||
|
||||
/* Pipes without underlay after */
|
||||
for (i = 0; i < pipe_count; i++) {
|
||||
unsigned int pixel_clock_khz;
|
||||
unsigned int pixel_clock_100hz;
|
||||
if (!pipe[i].stream || pipe[i].bottom_pipe)
|
||||
continue;
|
||||
|
||||
|
@ -2890,10 +2890,10 @@ static void populate_initial_data(
|
|||
data->lpt_en[num_displays + 4] = false;
|
||||
data->h_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.h_total);
|
||||
data->v_total[num_displays + 4] = bw_int_to_fixed(pipe[i].stream->timing.v_total);
|
||||
pixel_clock_khz = pipe[i].stream->timing.pix_clk_khz;
|
||||
pixel_clock_100hz = pipe[i].stream->timing.pix_clk_100hz;
|
||||
if (pipe[i].stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
|
||||
pixel_clock_khz *= 2;
|
||||
data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_khz, 1000);
|
||||
pixel_clock_100hz *= 2;
|
||||
data->pixel_rate[num_displays + 4] = bw_frc_to_fixed(pixel_clock_100hz, 10000);
|
||||
if (pipe[i].plane_state) {
|
||||
data->src_width[num_displays + 4] = bw_int_to_fixed(pipe[i].plane_res.scl_data.viewport.width);
|
||||
data->pitch_in_pixels[num_displays + 4] = data->src_width[num_displays + 4];
|
||||
|
|
|
@ -797,9 +797,40 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v)
|
|||
else {
|
||||
v->maximum_vstartup = v->v_sync_plus_back_porch[k] - 1.0;
|
||||
}
|
||||
v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]);
|
||||
v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4;
|
||||
v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]);
|
||||
|
||||
do {
|
||||
v->line_times_for_prefetch[k] = v->maximum_vstartup - v->urgent_latency / (v->htotal[k] / v->pixel_clock[k]) - (v->time_calc + v->time_setup) / (v->htotal[k] / v->pixel_clock[k]) - (v->dst_y_after_scaler + v->dst_x_after_scaler / v->htotal[k]);
|
||||
v->line_times_for_prefetch[k] =dcn_bw_floor2(4.0 * (v->line_times_for_prefetch[k] + 0.125), 1.0) / 4;
|
||||
v->prefetch_bw[k] = (v->meta_pte_bytes_per_frame[k] + 2.0 * v->meta_row_bytes[k] + 2.0 * v->dpte_bytes_per_row[k] + v->prefetch_lines_y[k] * v->swath_width_yper_state[i][j][k] *dcn_bw_ceil2(v->byte_per_pixel_in_dety[k], 1.0) + v->prefetch_lines_c[k] * v->swath_width_yper_state[i][j][k] / 2.0 *dcn_bw_ceil2(v->byte_per_pixel_in_detc[k], 2.0)) / (v->line_times_for_prefetch[k] * v->htotal[k] / v->pixel_clock[k]);
|
||||
|
||||
if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) {
|
||||
v->time_for_meta_pte_without_immediate_flip = dcn_bw_max3(
|
||||
v->meta_pte_bytes_frame[k] / v->prefetch_bandwidth[k],
|
||||
v->extra_latency,
|
||||
v->htotal[k] / v->pixel_clock[k] / 4.0);
|
||||
} else {
|
||||
v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
|
||||
}
|
||||
|
||||
if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) {
|
||||
v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max3((
|
||||
v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bandwidth[k],
|
||||
v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip,
|
||||
v->extra_latency);
|
||||
} else {
|
||||
v->time_for_meta_and_dpte_row_without_immediate_flip = dcn_bw_max2(
|
||||
v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip,
|
||||
v->extra_latency - v->time_for_meta_pte_with_immediate_flip);
|
||||
}
|
||||
|
||||
v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->maximum_vstartup = v->maximum_vstartup - 1;
|
||||
|
||||
if (v->lines_for_meta_pte_without_immediate_flip[k] < 8.0 && v->lines_for_meta_and_dpte_row_without_immediate_flip[k] < 16.0)
|
||||
break;
|
||||
|
||||
} while(1);
|
||||
}
|
||||
v->bw_available_for_immediate_flip = v->return_bw_per_state[i];
|
||||
for (k = 0; k <= v->number_of_active_planes - 1; k++) {
|
||||
|
@ -814,24 +845,18 @@ void mode_support_and_system_configuration(struct dcn_bw_internal_vars *v)
|
|||
for (k = 0; k <= v->number_of_active_planes - 1; k++) {
|
||||
if (v->pte_enable == dcn_bw_yes && v->dcc_enable[k] == dcn_bw_yes) {
|
||||
v->time_for_meta_pte_with_immediate_flip =dcn_bw_max5(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->meta_pte_bytes_per_frame[k] * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->extra_latency, v->urgent_latency, v->htotal[k] / v->pixel_clock[k] / 4.0);
|
||||
v->time_for_meta_pte_without_immediate_flip =dcn_bw_max3(v->meta_pte_bytes_per_frame[k] / v->prefetch_bw[k], v->extra_latency, v->htotal[k] / v->pixel_clock[k] / 4.0);
|
||||
}
|
||||
else {
|
||||
v->time_for_meta_pte_with_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
|
||||
v->time_for_meta_pte_without_immediate_flip = v->htotal[k] / v->pixel_clock[k] / 4.0;
|
||||
}
|
||||
if (v->pte_enable == dcn_bw_yes || v->dcc_enable[k] == dcn_bw_yes) {
|
||||
v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max5((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], (v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) * v->total_immediate_flip_bytes[k] / (v->bw_available_for_immediate_flip * (v->meta_pte_bytes_per_frame[k] + v->meta_row_bytes[k] + v->dpte_bytes_per_row[k])), v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency, 2.0 * v->urgent_latency);
|
||||
v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max3((v->meta_row_bytes[k] + v->dpte_bytes_per_row[k]) / v->prefetch_bw[k], v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency);
|
||||
}
|
||||
else {
|
||||
v->time_for_meta_and_dpte_row_with_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_with_immediate_flip, v->extra_latency - v->time_for_meta_pte_with_immediate_flip);
|
||||
v->time_for_meta_and_dpte_row_without_immediate_flip =dcn_bw_max2(v->htotal[k] / v->pixel_clock[k] - v->time_for_meta_pte_without_immediate_flip, v->extra_latency - v->time_for_meta_pte_without_immediate_flip);
|
||||
}
|
||||
v->lines_for_meta_pte_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->lines_for_meta_pte_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_pte_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->lines_for_meta_and_dpte_row_with_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_with_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->lines_for_meta_and_dpte_row_without_immediate_flip[k] =dcn_bw_floor2(4.0 * (v->time_for_meta_and_dpte_row_without_immediate_flip / (v->htotal[k] / v->pixel_clock[k]) + 0.125), 1.0) / 4;
|
||||
v->line_times_to_request_prefetch_pixel_data_with_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_with_immediate_flip[k] - v->lines_for_meta_and_dpte_row_with_immediate_flip[k];
|
||||
v->line_times_to_request_prefetch_pixel_data_without_immediate_flip = v->line_times_for_prefetch[k] - v->lines_for_meta_pte_without_immediate_flip[k] - v->lines_for_meta_and_dpte_row_without_immediate_flip[k];
|
||||
if (v->line_times_to_request_prefetch_pixel_data_with_immediate_flip > 0.0) {
|
||||
|
|
|
@ -290,41 +290,34 @@ static void pipe_ctx_to_e2e_pipe_params (
|
|||
switch (pipe->plane_state->tiling_info.gfx9.swizzle) {
|
||||
/* for 4/8/16 high tiles */
|
||||
case DC_SW_LINEAR:
|
||||
input->src.is_display_sw = 1;
|
||||
input->src.macro_tile_size = dm_4k_tile;
|
||||
break;
|
||||
case DC_SW_4KB_S:
|
||||
case DC_SW_4KB_S_X:
|
||||
input->src.is_display_sw = 0;
|
||||
input->src.macro_tile_size = dm_4k_tile;
|
||||
break;
|
||||
case DC_SW_64KB_S:
|
||||
case DC_SW_64KB_S_X:
|
||||
case DC_SW_64KB_S_T:
|
||||
input->src.is_display_sw = 0;
|
||||
input->src.macro_tile_size = dm_64k_tile;
|
||||
break;
|
||||
case DC_SW_VAR_S:
|
||||
case DC_SW_VAR_S_X:
|
||||
input->src.is_display_sw = 0;
|
||||
input->src.macro_tile_size = dm_256k_tile;
|
||||
break;
|
||||
|
||||
/* For 64bpp 2 high tiles */
|
||||
case DC_SW_4KB_D:
|
||||
case DC_SW_4KB_D_X:
|
||||
input->src.is_display_sw = 1;
|
||||
input->src.macro_tile_size = dm_4k_tile;
|
||||
break;
|
||||
case DC_SW_64KB_D:
|
||||
case DC_SW_64KB_D_X:
|
||||
case DC_SW_64KB_D_T:
|
||||
input->src.is_display_sw = 1;
|
||||
input->src.macro_tile_size = dm_64k_tile;
|
||||
break;
|
||||
case DC_SW_VAR_D:
|
||||
case DC_SW_VAR_D_X:
|
||||
input->src.is_display_sw = 1;
|
||||
input->src.macro_tile_size = dm_256k_tile;
|
||||
break;
|
||||
|
||||
|
@ -423,7 +416,7 @@ static void pipe_ctx_to_e2e_pipe_params (
|
|||
- pipe->stream->timing.v_addressable
|
||||
- pipe->stream->timing.v_border_bottom
|
||||
- pipe->stream->timing.v_border_top;
|
||||
input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0;
|
||||
input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_100hz/10000.0;
|
||||
input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start;
|
||||
input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset;
|
||||
input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset;
|
||||
|
@ -670,9 +663,9 @@ static void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v)
|
|||
}
|
||||
|
||||
static void hack_force_pipe_split(struct dcn_bw_internal_vars *v,
|
||||
unsigned int pixel_rate_khz)
|
||||
unsigned int pixel_rate_100hz)
|
||||
{
|
||||
float pixel_rate_mhz = pixel_rate_khz / 1000;
|
||||
float pixel_rate_mhz = pixel_rate_100hz / 10000;
|
||||
|
||||
/*
|
||||
* force enabling pipe split by lower dpp clock for DPM0 to just
|
||||
|
@ -695,7 +688,7 @@ static void hack_bounding_box(struct dcn_bw_internal_vars *v,
|
|||
|
||||
if (context->stream_count == 1 &&
|
||||
dbg->force_single_disp_pipe_split)
|
||||
hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_khz);
|
||||
hack_force_pipe_split(v, context->streams[0]->timing.pix_clk_100hz);
|
||||
}
|
||||
|
||||
bool dcn_validate_bandwidth(
|
||||
|
@ -852,7 +845,7 @@ bool dcn_validate_bandwidth(
|
|||
v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total
|
||||
- v->vactive[input_idx]
|
||||
- pipe->stream->timing.v_front_porch;
|
||||
v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz/1000.0;
|
||||
v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_100hz/10000.0;
|
||||
if (pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
|
||||
v->pixel_clock[input_idx] *= 2;
|
||||
if (!pipe->plane_state) {
|
||||
|
@ -961,7 +954,7 @@ bool dcn_validate_bandwidth(
|
|||
v->dcc_rate[input_idx] = 1; /*TODO: Worst case? does this change?*/
|
||||
v->output_format[input_idx] = pipe->stream->timing.pixel_encoding ==
|
||||
PIXEL_ENCODING_YCBCR420 ? dcn_bw_420 : dcn_bw_444;
|
||||
v->output[input_idx] = pipe->stream->sink->sink_signal ==
|
||||
v->output[input_idx] = pipe->stream->signal ==
|
||||
SIGNAL_TYPE_HDMI_TYPE_A ? dcn_bw_hdmi : dcn_bw_dp;
|
||||
v->output_deep_color[input_idx] = dcn_bw_encoder_8bpc;
|
||||
if (v->output[input_idx] == dcn_bw_hdmi) {
|
||||
|
|
|
@ -384,7 +384,7 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
|
|||
enum dc_dither_option option)
|
||||
{
|
||||
struct bit_depth_reduction_params params;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
struct pipe_ctx *pipes = NULL;
|
||||
int i;
|
||||
|
||||
|
@ -451,7 +451,7 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
|
|||
pipes,
|
||||
stream->output_color_space,
|
||||
stream->csc_color_matrix.matrix,
|
||||
pipes->plane_res.hubp->opp_id);
|
||||
pipes->plane_res.hubp ? pipes->plane_res.hubp->opp_id : 0);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -526,9 +526,8 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
|
|||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
if (pipe->stream && pipe->stream->sink
|
||||
&& pipe->stream->sink->link) {
|
||||
if (pipe->stream->sink->link == link)
|
||||
if (pipe->stream && pipe->stream->link) {
|
||||
if (pipe->stream->link == link)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -586,9 +585,6 @@ static void destruct(struct dc *dc)
|
|||
if (dc->ctx->gpio_service)
|
||||
dal_gpio_service_destroy(&dc->ctx->gpio_service);
|
||||
|
||||
if (dc->ctx->i2caux)
|
||||
dal_i2caux_destroy(&dc->ctx->i2caux);
|
||||
|
||||
if (dc->ctx->created_bios)
|
||||
dal_bios_parser_destroy(&dc->ctx->dc_bios);
|
||||
|
||||
|
@ -670,6 +666,7 @@ static bool construct(struct dc *dc,
|
|||
dc_ctx->dc = dc;
|
||||
dc_ctx->asic_id = init_params->asic_id;
|
||||
dc_ctx->dc_sink_id_count = 0;
|
||||
dc_ctx->dc_stream_id_count = 0;
|
||||
dc->ctx = dc_ctx;
|
||||
|
||||
dc->current_state = dc_create_state();
|
||||
|
@ -709,14 +706,6 @@ static bool construct(struct dc *dc,
|
|||
dc_ctx->created_bios = true;
|
||||
}
|
||||
|
||||
/* Create I2C AUX */
|
||||
dc_ctx->i2caux = dal_i2caux_create(dc_ctx);
|
||||
|
||||
if (!dc_ctx->i2caux) {
|
||||
ASSERT_CRITICAL(false);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dc_ctx->perf_trace = dc_perf_trace_create();
|
||||
if (!dc_ctx->perf_trace) {
|
||||
ASSERT_CRITICAL(false);
|
||||
|
@ -840,6 +829,11 @@ struct dc *dc_create(const struct dc_init_data *init_params)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void dc_init_callbacks(struct dc *dc,
|
||||
const struct dc_callback_init *init_params)
|
||||
{
|
||||
}
|
||||
|
||||
void dc_destroy(struct dc **dc)
|
||||
{
|
||||
destruct(*dc);
|
||||
|
@ -1040,7 +1034,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|||
|
||||
/* Program all planes within new context*/
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
const struct dc_sink *sink = context->streams[i]->sink;
|
||||
const struct dc_link *link = context->streams[i]->link;
|
||||
struct dc_stream_status *status;
|
||||
|
||||
if (!context->streams[i]->mode_changed)
|
||||
continue;
|
||||
|
@ -1065,12 +1060,15 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|||
}
|
||||
}
|
||||
|
||||
CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
|
||||
status = dc_stream_get_status_from_state(context, context->streams[i]);
|
||||
context->streams[i]->out.otg_offset = status->primary_otg_inst;
|
||||
|
||||
CONN_MSG_MODE(link, "{%dx%d, %dx%d@%dKhz}",
|
||||
context->streams[i]->timing.h_addressable,
|
||||
context->streams[i]->timing.v_addressable,
|
||||
context->streams[i]->timing.h_total,
|
||||
context->streams[i]->timing.v_total,
|
||||
context->streams[i]->timing.pix_clk_khz);
|
||||
context->streams[i]->timing.pix_clk_100hz / 10);
|
||||
}
|
||||
|
||||
dc_enable_stereo(dc, context, dc_streams, context->stream_count);
|
||||
|
@ -1215,6 +1213,12 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
|
|||
*/
|
||||
update_flags->bits.bpp_change = 1;
|
||||
|
||||
if (u->plane_info->plane_size.grph.surface_pitch != u->surface->plane_size.grph.surface_pitch
|
||||
|| u->plane_info->plane_size.video.luma_pitch != u->surface->plane_size.video.luma_pitch
|
||||
|| u->plane_info->plane_size.video.chroma_pitch != u->surface->plane_size.video.chroma_pitch)
|
||||
update_flags->bits.plane_size_change = 1;
|
||||
|
||||
|
||||
if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
|
||||
sizeof(union dc_tiling_info)) != 0) {
|
||||
update_flags->bits.swizzle_change = 1;
|
||||
|
@ -1236,7 +1240,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
|
|||
|| update_flags->bits.output_tf_change)
|
||||
return UPDATE_TYPE_FULL;
|
||||
|
||||
return UPDATE_TYPE_MED;
|
||||
return update_flags->raw ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST;
|
||||
}
|
||||
|
||||
static enum surface_update_type get_scaling_info_update_type(
|
||||
|
@ -1605,7 +1609,6 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
int surface_count,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_stream_update *stream_update,
|
||||
struct dc_plane_state **plane_states,
|
||||
struct dc_state *state)
|
||||
{
|
||||
const struct dc_stream_status *stream_status;
|
||||
|
@ -1764,6 +1767,26 @@ void dc_resume(struct dc *dc)
|
|||
core_link_resume(dc->links[i]);
|
||||
}
|
||||
|
||||
unsigned int dc_get_current_backlight_pwm(struct dc *dc)
|
||||
{
|
||||
struct abm *abm = dc->res_pool->abm;
|
||||
|
||||
if (abm)
|
||||
return abm->funcs->get_current_backlight(abm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int dc_get_target_backlight_pwm(struct dc *dc)
|
||||
{
|
||||
struct abm *abm = dc->res_pool->abm;
|
||||
|
||||
if (abm)
|
||||
return abm->funcs->get_target_backlight(abm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool dc_is_dmcu_initialized(struct dc *dc)
|
||||
{
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
|
|
|
@ -43,10 +43,6 @@
|
|||
#include "dpcd_defs.h"
|
||||
#include "dmcu.h"
|
||||
|
||||
#include "dce/dce_11_0_d.h"
|
||||
#include "dce/dce_11_0_enum.h"
|
||||
#include "dce/dce_11_0_sh_mask.h"
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
|
||||
|
@ -789,7 +785,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
|
|||
return false;
|
||||
}
|
||||
|
||||
sink->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
|
||||
sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
|
||||
sink->converter_disable_audio = converter_disable_audio;
|
||||
|
||||
link->local_sink = sink;
|
||||
|
@ -1372,7 +1368,7 @@ static void dpcd_configure_panel_mode(
|
|||
static void enable_stream_features(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
union down_spread_ctrl old_downspread;
|
||||
union down_spread_ctrl new_downspread;
|
||||
|
||||
|
@ -1397,7 +1393,7 @@ static enum dc_status enable_link_dp(
|
|||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
enum dc_status status;
|
||||
bool skip_video_pattern;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
struct dc_link_settings link_settings = {0};
|
||||
enum dp_panel_mode panel_mode;
|
||||
|
||||
|
@ -1414,8 +1410,8 @@ static enum dc_status enable_link_dp(
|
|||
pipe_ctx->clock_source->id,
|
||||
&link_settings);
|
||||
|
||||
if (stream->sink->edid_caps.panel_patch.dppowerup_delay > 0) {
|
||||
int delay_dp_power_up_in_ms = stream->sink->edid_caps.panel_patch.dppowerup_delay;
|
||||
if (stream->sink_patches.dppowerup_delay > 0) {
|
||||
int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
|
||||
|
||||
msleep(delay_dp_power_up_in_ms);
|
||||
}
|
||||
|
@ -1448,7 +1444,7 @@ static enum dc_status enable_link_edp(
|
|||
{
|
||||
enum dc_status status;
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
/*in case it is not on*/
|
||||
link->dc->hwss.edp_power_control(link, true);
|
||||
link->dc->hwss.edp_wait_for_hpd_ready(link, true);
|
||||
|
@ -1463,7 +1459,7 @@ static enum dc_status enable_link_dp_mst(
|
|||
struct dc_state *state,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_link *link = pipe_ctx->stream->sink->link;
|
||||
struct dc_link *link = pipe_ctx->stream->link;
|
||||
|
||||
/* sink signal type after MST branch is MST. Multiple MST sinks
|
||||
* share one link. Link DP PHY is enable or training only once.
|
||||
|
@ -1597,7 +1593,7 @@ static bool i2c_write(struct pipe_ctx *pipe_ctx,
|
|||
cmd.payloads = &payload;
|
||||
|
||||
if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
|
||||
pipe_ctx->stream->sink->link, &cmd))
|
||||
pipe_ctx->stream->link, &cmd))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -1651,7 +1647,7 @@ static void write_i2c_retimer_setting(
|
|||
else {
|
||||
i2c_success =
|
||||
dal_ddc_service_query_ddc_data(
|
||||
pipe_ctx->stream->sink->link->ddc,
|
||||
pipe_ctx->stream->link->ddc,
|
||||
slave_address, &offset, 1, &value, 1);
|
||||
if (!i2c_success)
|
||||
/* Write failure */
|
||||
|
@ -1704,7 +1700,7 @@ static void write_i2c_retimer_setting(
|
|||
else {
|
||||
i2c_success =
|
||||
dal_ddc_service_query_ddc_data(
|
||||
pipe_ctx->stream->sink->link->ddc,
|
||||
pipe_ctx->stream->link->ddc,
|
||||
slave_address, &offset, 1, &value, 1);
|
||||
if (!i2c_success)
|
||||
/* Write failure */
|
||||
|
@ -1929,7 +1925,7 @@ static void write_i2c_redriver_setting(
|
|||
static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
enum dc_color_depth display_color_depth;
|
||||
enum engine_id eng_id;
|
||||
struct ext_hdmi_settings settings = {0};
|
||||
|
@ -1938,12 +1934,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
|
|||
&& (stream->timing.v_addressable == 480);
|
||||
|
||||
if (stream->phy_pix_clk == 0)
|
||||
stream->phy_pix_clk = stream->timing.pix_clk_khz;
|
||||
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
|
||||
if (stream->phy_pix_clk > 340000)
|
||||
is_over_340mhz = true;
|
||||
|
||||
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
|
||||
unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps &
|
||||
unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &
|
||||
EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
|
||||
if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
|
||||
/* DP159, Retimer settings */
|
||||
|
@ -1964,11 +1960,11 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
|
|||
|
||||
if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
|
||||
dal_ddc_service_write_scdc_data(
|
||||
stream->sink->link->ddc,
|
||||
stream->link->ddc,
|
||||
stream->phy_pix_clk,
|
||||
stream->timing.flags.LTE_340MCSC_SCRAMBLE);
|
||||
|
||||
memset(&stream->sink->link->cur_link_settings, 0,
|
||||
memset(&stream->link->cur_link_settings, 0,
|
||||
sizeof(struct dc_link_settings));
|
||||
|
||||
display_color_depth = stream->timing.display_color_depth;
|
||||
|
@ -1989,12 +1985,12 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
|
|||
static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
|
||||
if (stream->phy_pix_clk == 0)
|
||||
stream->phy_pix_clk = stream->timing.pix_clk_khz;
|
||||
stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
|
||||
|
||||
memset(&stream->sink->link->cur_link_settings, 0,
|
||||
memset(&stream->link->cur_link_settings, 0,
|
||||
sizeof(struct dc_link_settings));
|
||||
|
||||
link->link_enc->funcs->enable_lvds_output(
|
||||
|
@ -2067,7 +2063,7 @@ static bool dp_active_dongle_validate_timing(
|
|||
const struct dc_crtc_timing *timing,
|
||||
const struct dpcd_caps *dpcd_caps)
|
||||
{
|
||||
unsigned int required_pix_clk = timing->pix_clk_khz;
|
||||
unsigned int required_pix_clk_100hz = timing->pix_clk_100hz;
|
||||
const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
|
||||
|
||||
switch (dpcd_caps->dongle_type) {
|
||||
|
@ -2107,9 +2103,9 @@ static bool dp_active_dongle_validate_timing(
|
|||
|
||||
/* Check Color Depth and Pixel Clock */
|
||||
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
required_pix_clk /= 2;
|
||||
required_pix_clk_100hz /= 2;
|
||||
else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
|
||||
required_pix_clk = required_pix_clk * 2 / 3;
|
||||
required_pix_clk_100hz = required_pix_clk_100hz * 2 / 3;
|
||||
|
||||
switch (timing->display_color_depth) {
|
||||
case COLOR_DEPTH_666:
|
||||
|
@ -2119,12 +2115,12 @@ static bool dp_active_dongle_validate_timing(
|
|||
case COLOR_DEPTH_101010:
|
||||
if (dongle_caps->dp_hdmi_max_bpc < 10)
|
||||
return false;
|
||||
required_pix_clk = required_pix_clk * 10 / 8;
|
||||
required_pix_clk_100hz = required_pix_clk_100hz * 10 / 8;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
if (dongle_caps->dp_hdmi_max_bpc < 12)
|
||||
return false;
|
||||
required_pix_clk = required_pix_clk * 12 / 8;
|
||||
required_pix_clk_100hz = required_pix_clk_100hz * 12 / 8;
|
||||
break;
|
||||
|
||||
case COLOR_DEPTH_141414:
|
||||
|
@ -2134,7 +2130,7 @@ static bool dp_active_dongle_validate_timing(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (required_pix_clk > dongle_caps->dp_hdmi_max_pixel_clk)
|
||||
if (required_pix_clk_100hz > (dongle_caps->dp_hdmi_max_pixel_clk * 10))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -2145,7 +2141,7 @@ enum dc_status dc_link_validate_mode_timing(
|
|||
struct dc_link *link,
|
||||
const struct dc_crtc_timing *timing)
|
||||
{
|
||||
uint32_t max_pix_clk = stream->sink->dongle_max_pix_clk;
|
||||
uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
|
||||
struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
|
||||
|
||||
/* A hack to avoid failing any modes for EDID override feature on
|
||||
|
@ -2155,7 +2151,7 @@ enum dc_status dc_link_validate_mode_timing(
|
|||
return DC_OK;
|
||||
|
||||
/* Passive Dongle */
|
||||
if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
|
||||
if (0 != max_pix_clk && timing->pix_clk_100hz > max_pix_clk)
|
||||
return DC_EXCEED_DONGLE_CAP;
|
||||
|
||||
/* Active Dongle*/
|
||||
|
@ -2190,8 +2186,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
|
|||
|
||||
bool dc_link_set_backlight_level(const struct dc_link *link,
|
||||
uint32_t backlight_pwm_u16_16,
|
||||
uint32_t frame_ramp,
|
||||
const struct dc_stream_state *stream)
|
||||
uint32_t frame_ramp)
|
||||
{
|
||||
struct dc *core_dc = link->ctx->dc;
|
||||
struct abm *abm = core_dc->res_pool->abm;
|
||||
|
@ -2206,10 +2201,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
|
|||
(abm->funcs->set_backlight_level_pwm == NULL))
|
||||
return false;
|
||||
|
||||
if (stream)
|
||||
((struct dc_stream_state *)stream)->bl_pwm_level =
|
||||
backlight_pwm_u16_16;
|
||||
|
||||
use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
|
||||
|
||||
DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
|
||||
|
@ -2219,7 +2210,7 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
|
|||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) {
|
||||
if (core_dc->current_state->res_ctx.
|
||||
pipe_ctx[i].stream->sink->link
|
||||
pipe_ctx[i].stream->link
|
||||
== link)
|
||||
/* DMCU -1 for all controller id values,
|
||||
* therefore +1 here
|
||||
|
@ -2279,7 +2270,7 @@ void core_link_resume(struct dc_link *link)
|
|||
static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
|
||||
{
|
||||
struct dc_link_settings *link_settings =
|
||||
&stream->sink->link->cur_link_settings;
|
||||
&stream->link->cur_link_settings;
|
||||
uint32_t link_rate_in_mbps =
|
||||
link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
|
||||
struct fixed31_32 mbps = dc_fixpt_from_int(
|
||||
|
@ -2310,7 +2301,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
|
|||
uint32_t denominator;
|
||||
|
||||
bpc = get_color_depth(pipe_ctx->stream_res.pix_clk_params.color_depth);
|
||||
kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk * bpc * 3;
|
||||
kbps = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 * bpc * 3;
|
||||
|
||||
/*
|
||||
* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
|
||||
|
@ -2386,7 +2377,7 @@ static void update_mst_stream_alloc_table(
|
|||
static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
struct link_encoder *link_encoder = link->link_enc;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
|
@ -2466,7 +2457,7 @@ static enum dc_status allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
|||
static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
struct link_encoder *link_encoder = link->link_enc;
|
||||
struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;
|
||||
struct dp_mst_stream_allocation_table proposed_table = {0};
|
||||
|
@ -2551,8 +2542,8 @@ void core_link_enable_stream(
|
|||
DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
|
||||
|
||||
if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) {
|
||||
stream->sink->link->link_enc->funcs->setup(
|
||||
stream->sink->link->link_enc,
|
||||
stream->link->link_enc->funcs->setup(
|
||||
stream->link->link_enc,
|
||||
pipe_ctx->stream->signal);
|
||||
pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
|
||||
pipe_ctx->stream_res.stream_enc,
|
||||
|
@ -2604,7 +2595,7 @@ void core_link_enable_stream(
|
|||
|
||||
if (status != DC_OK) {
|
||||
DC_LOG_WARNING("enabling link %u failed: %d\n",
|
||||
pipe_ctx->stream->sink->link->link_index,
|
||||
pipe_ctx->stream->link->link_index,
|
||||
status);
|
||||
|
||||
/* Abort stream enable *unless* the failure was due to
|
||||
|
@ -2633,15 +2624,10 @@ void core_link_enable_stream(
|
|||
allocate_mst_payload(pipe_ctx);
|
||||
|
||||
core_dc->hwss.unblank_stream(pipe_ctx,
|
||||
&pipe_ctx->stream->sink->link->cur_link_settings);
|
||||
&pipe_ctx->stream->link->cur_link_settings);
|
||||
|
||||
if (dc_is_dp_signal(pipe_ctx->stream->signal))
|
||||
enable_stream_features(pipe_ctx);
|
||||
|
||||
dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
|
||||
pipe_ctx->stream->bl_pwm_level,
|
||||
0,
|
||||
pipe_ctx->stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2657,7 +2643,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
|
|||
|
||||
core_dc->hwss.disable_stream(pipe_ctx, option);
|
||||
|
||||
disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
|
||||
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
|
||||
}
|
||||
|
||||
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "include/vector.h"
|
||||
#include "core_types.h"
|
||||
#include "dc_link_ddc.h"
|
||||
#include "aux_engine.h"
|
||||
#include "dce/dce_aux.h"
|
||||
|
||||
#define AUX_POWER_UP_WA_DELAY 500
|
||||
#define I2C_OVER_AUX_DEFER_WA_DELAY 70
|
||||
|
@ -42,7 +42,6 @@
|
|||
#define CV_SMART_DONGLE_ADDRESS 0x20
|
||||
/* DVI-HDMI dongle slave address for retrieving dongle signature*/
|
||||
#define DVI_HDMI_DONGLE_ADDRESS 0x68
|
||||
static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G";
|
||||
struct dvi_hdmi_dongle_signature_data {
|
||||
int8_t vendor[3];/* "AMD" */
|
||||
uint8_t version[2];
|
||||
|
@ -165,43 +164,6 @@ static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
|
|||
|
||||
}
|
||||
|
||||
static struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
|
||||
{
|
||||
struct aux_payloads *payloads;
|
||||
|
||||
payloads = kzalloc(sizeof(struct aux_payloads), GFP_KERNEL);
|
||||
|
||||
if (!payloads)
|
||||
return NULL;
|
||||
|
||||
if (dal_vector_construct(
|
||||
&payloads->payloads, ctx, count, sizeof(struct aux_payload)))
|
||||
return payloads;
|
||||
|
||||
kfree(payloads);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p)
|
||||
{
|
||||
return (struct aux_payload *)p->payloads.container;
|
||||
}
|
||||
|
||||
static uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p)
|
||||
{
|
||||
return p->payloads.count;
|
||||
}
|
||||
|
||||
static void dal_ddc_aux_payloads_destroy(struct aux_payloads **p)
|
||||
{
|
||||
if (!p || !*p)
|
||||
return;
|
||||
|
||||
dal_vector_destruct(&(*p)->payloads);
|
||||
kfree(*p);
|
||||
*p = NULL;
|
||||
}
|
||||
|
||||
#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
void dal_ddc_i2c_payloads_add(
|
||||
|
@ -225,27 +187,6 @@ void dal_ddc_i2c_payloads_add(
|
|||
|
||||
}
|
||||
|
||||
void dal_ddc_aux_payloads_add(
|
||||
struct aux_payloads *payloads,
|
||||
uint32_t address,
|
||||
uint32_t len,
|
||||
uint8_t *data,
|
||||
bool write)
|
||||
{
|
||||
uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE;
|
||||
uint32_t pos;
|
||||
|
||||
for (pos = 0; pos < len; pos += payload_size) {
|
||||
struct aux_payload payload = {
|
||||
.i2c_over_aux = true,
|
||||
.write = write,
|
||||
.address = address,
|
||||
.length = DDC_MIN(payload_size, len - pos),
|
||||
.data = data + pos };
|
||||
dal_vector_append(&payloads->payloads, &payload);
|
||||
}
|
||||
}
|
||||
|
||||
static void construct(
|
||||
struct ddc_service *ddc_service,
|
||||
struct ddc_service_init_data *init_data)
|
||||
|
@ -574,32 +515,34 @@ bool dal_ddc_service_query_ddc_data(
|
|||
/*TODO: len of payload data for i2c and aux is uint8!!!!,
|
||||
* but we want to read 256 over i2c!!!!*/
|
||||
if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
|
||||
|
||||
struct aux_payloads *payloads =
|
||||
dal_ddc_aux_payloads_create(ddc->ctx, payloads_num);
|
||||
|
||||
struct aux_command command = {
|
||||
.payloads = dal_ddc_aux_payloads_get(payloads),
|
||||
.number_of_payloads = 0,
|
||||
struct aux_payload write_payload = {
|
||||
.i2c_over_aux = true,
|
||||
.write = true,
|
||||
.mot = true,
|
||||
.address = address,
|
||||
.length = write_size,
|
||||
.data = write_buf,
|
||||
.reply = NULL,
|
||||
.defer_delay = get_defer_delay(ddc),
|
||||
.max_defer_write_retry = 0 };
|
||||
};
|
||||
|
||||
dal_ddc_aux_payloads_add(
|
||||
payloads, address, write_size, write_buf, true);
|
||||
struct aux_payload read_payload = {
|
||||
.i2c_over_aux = true,
|
||||
.write = false,
|
||||
.mot = false,
|
||||
.address = address,
|
||||
.length = read_size,
|
||||
.data = read_buf,
|
||||
.reply = NULL,
|
||||
.defer_delay = get_defer_delay(ddc),
|
||||
};
|
||||
|
||||
dal_ddc_aux_payloads_add(
|
||||
payloads, address, read_size, read_buf, false);
|
||||
ret = dc_link_aux_transfer_with_retries(ddc, &write_payload);
|
||||
|
||||
command.number_of_payloads =
|
||||
dal_ddc_aux_payloads_get_count(payloads);
|
||||
|
||||
ret = dal_i2caux_submit_aux_command(
|
||||
ddc->ctx->i2caux,
|
||||
ddc->ddc_pin,
|
||||
&command);
|
||||
|
||||
dal_ddc_aux_payloads_destroy(&payloads);
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
ret = dc_link_aux_transfer_with_retries(ddc, &read_payload);
|
||||
} else {
|
||||
struct i2c_payloads *payloads =
|
||||
dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
|
||||
|
@ -631,56 +574,15 @@ bool dal_ddc_service_query_ddc_data(
|
|||
}
|
||||
|
||||
int dc_link_aux_transfer(struct ddc_service *ddc,
|
||||
unsigned int address,
|
||||
uint8_t *reply,
|
||||
void *buffer,
|
||||
unsigned int size,
|
||||
enum aux_transaction_type type,
|
||||
enum i2caux_transaction_action action)
|
||||
struct aux_payload *payload)
|
||||
{
|
||||
struct ddc *ddc_pin = ddc->ddc_pin;
|
||||
struct aux_engine *aux_engine;
|
||||
enum aux_channel_operation_result operation_result;
|
||||
struct aux_request_transaction_data aux_req;
|
||||
struct aux_reply_transaction_data aux_rep;
|
||||
uint8_t returned_bytes = 0;
|
||||
int res = -1;
|
||||
uint32_t status;
|
||||
return dce_aux_transfer(ddc, payload);
|
||||
}
|
||||
|
||||
memset(&aux_req, 0, sizeof(aux_req));
|
||||
memset(&aux_rep, 0, sizeof(aux_rep));
|
||||
|
||||
aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
|
||||
aux_engine->funcs->acquire(aux_engine, ddc_pin);
|
||||
|
||||
aux_req.type = type;
|
||||
aux_req.action = action;
|
||||
|
||||
aux_req.address = address;
|
||||
aux_req.delay = 0;
|
||||
aux_req.length = size;
|
||||
aux_req.data = buffer;
|
||||
|
||||
aux_engine->funcs->submit_channel_request(aux_engine, &aux_req);
|
||||
operation_result = aux_engine->funcs->get_channel_status(aux_engine, &returned_bytes);
|
||||
|
||||
switch (operation_result) {
|
||||
case AUX_CHANNEL_OPERATION_SUCCEEDED:
|
||||
res = aux_engine->funcs->read_channel_reply(aux_engine, size,
|
||||
buffer, reply,
|
||||
&status);
|
||||
break;
|
||||
case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
|
||||
res = 0;
|
||||
break;
|
||||
case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
|
||||
case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
|
||||
case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
aux_engine->funcs->release_engine(aux_engine);
|
||||
return res;
|
||||
bool dc_link_aux_transfer_with_retries(struct ddc_service *ddc,
|
||||
struct aux_payload *payload)
|
||||
{
|
||||
return dce_aux_transfer_with_retries(ddc, payload);
|
||||
}
|
||||
|
||||
/*test only function*/
|
||||
|
|
|
@ -47,7 +47,7 @@ static void wait_for_training_aux_rd_interval(
|
|||
struct dc_link *link,
|
||||
uint32_t default_wait_in_micro_secs)
|
||||
{
|
||||
union training_aux_rd_interval training_rd_interval;
|
||||
union training_aux_rd_interval training_rd_interval = {0};
|
||||
|
||||
/* overwrite the delay if rev > 1.1*/
|
||||
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
|
||||
|
@ -117,6 +117,13 @@ static void dpcd_set_link_settings(
|
|||
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
|
||||
&downspread.raw, sizeof(downspread));
|
||||
|
||||
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
|
||||
(link->dpcd_caps.link_rate_set >= 1 &&
|
||||
link->dpcd_caps.link_rate_set <= 8)) {
|
||||
core_link_write_dpcd(link, DP_LINK_RATE_SET,
|
||||
&link->dpcd_caps.link_rate_set, 1);
|
||||
}
|
||||
|
||||
DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
|
||||
__func__,
|
||||
DP_LINK_BW_SET,
|
||||
|
@ -1542,7 +1549,7 @@ static uint32_t bandwidth_in_kbps_from_timing(
|
|||
|
||||
ASSERT(bits_per_channel != 0);
|
||||
|
||||
kbps = timing->pix_clk_khz;
|
||||
kbps = timing->pix_clk_100hz / 10;
|
||||
kbps *= bits_per_channel;
|
||||
|
||||
if (timing->flags.Y_ONLY != 1) {
|
||||
|
@ -1584,7 +1591,7 @@ bool dp_validate_mode_timing(
|
|||
const struct dc_link_settings *link_setting;
|
||||
|
||||
/*always DP fail safe mode*/
|
||||
if (timing->pix_clk_khz == (uint32_t) 25175 &&
|
||||
if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
|
||||
timing->h_addressable == (uint32_t) 640 &&
|
||||
timing->v_addressable == (uint32_t) 480)
|
||||
return true;
|
||||
|
@ -1634,7 +1641,7 @@ void decide_link_settings(struct dc_stream_state *stream,
|
|||
|
||||
req_bw = bandwidth_in_kbps_from_timing(&stream->timing);
|
||||
|
||||
link = stream->sink->link;
|
||||
link = stream->link;
|
||||
|
||||
/* if preferred is specified through AMDDP, use it, if it's enough
|
||||
* to drive the mode
|
||||
|
@ -1656,7 +1663,7 @@ void decide_link_settings(struct dc_stream_state *stream,
|
|||
}
|
||||
|
||||
/* EDP use the link cap setting */
|
||||
if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
|
||||
if (link->connector_signal == SIGNAL_TYPE_EDP) {
|
||||
*link_setting = link->verified_link_cap;
|
||||
return;
|
||||
}
|
||||
|
@ -2002,11 +2009,7 @@ static void handle_automated_test(struct dc_link *link)
|
|||
dp_test_send_phy_test_pattern(link);
|
||||
test_response.bits.ACK = 1;
|
||||
}
|
||||
if (!test_request.raw)
|
||||
/* no requests, revert all test signals
|
||||
* TODO: revert all test signals
|
||||
*/
|
||||
test_response.bits.ACK = 1;
|
||||
|
||||
/* send request acknowledgment */
|
||||
if (test_response.bits.ACK)
|
||||
core_link_write_dpcd(
|
||||
|
@ -2493,13 +2496,105 @@ bool detect_dp_sink_caps(struct dc_link *link)
|
|||
/* TODO save sink caps in link->sink */
|
||||
}
|
||||
|
||||
enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
|
||||
{
|
||||
enum dc_link_rate link_rate;
|
||||
// LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
|
||||
switch (link_rate_in_khz) {
|
||||
case 1620000:
|
||||
link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
|
||||
break;
|
||||
case 2160000:
|
||||
link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
|
||||
break;
|
||||
case 2430000:
|
||||
link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
|
||||
break;
|
||||
case 2700000:
|
||||
link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
|
||||
break;
|
||||
case 3240000:
|
||||
link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
|
||||
break;
|
||||
case 4320000:
|
||||
link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
|
||||
break;
|
||||
case 5400000:
|
||||
link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
|
||||
break;
|
||||
case 8100000:
|
||||
link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
|
||||
break;
|
||||
default:
|
||||
link_rate = LINK_RATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return link_rate;
|
||||
}
|
||||
|
||||
void detect_edp_sink_caps(struct dc_link *link)
|
||||
{
|
||||
uint8_t supported_link_rates[16] = {0};
|
||||
uint32_t entry;
|
||||
uint32_t link_rate_in_khz;
|
||||
enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
|
||||
uint8_t link_rate_set = 0;
|
||||
|
||||
retrieve_link_cap(link);
|
||||
|
||||
if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)
|
||||
link->reported_link_cap.link_rate = LINK_RATE_HIGH2;
|
||||
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
|
||||
// Read DPCD 00010h - 0001Fh 16 bytes at one shot
|
||||
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
|
||||
supported_link_rates, sizeof(supported_link_rates));
|
||||
|
||||
link->dpcd_caps.link_rate_set = 0;
|
||||
for (entry = 0; entry < 16; entry += 2) {
|
||||
// DPCD register reports per-lane link rate = 16-bit link rate capability
|
||||
// value X 200 kHz. Need multipler to find link rate in kHz.
|
||||
link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
|
||||
supported_link_rates[entry]) * 200;
|
||||
|
||||
if (link_rate_in_khz != 0) {
|
||||
link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
|
||||
if (link->reported_link_cap.link_rate < link_rate) {
|
||||
link->reported_link_cap.link_rate = link_rate;
|
||||
|
||||
switch (link_rate) {
|
||||
case LINK_RATE_LOW:
|
||||
link_rate_set = 1;
|
||||
break;
|
||||
case LINK_RATE_RATE_2:
|
||||
link_rate_set = 2;
|
||||
break;
|
||||
case LINK_RATE_RATE_3:
|
||||
link_rate_set = 3;
|
||||
break;
|
||||
case LINK_RATE_HIGH:
|
||||
link_rate_set = 4;
|
||||
break;
|
||||
case LINK_RATE_RBR2:
|
||||
link_rate_set = 5;
|
||||
break;
|
||||
case LINK_RATE_RATE_6:
|
||||
link_rate_set = 6;
|
||||
break;
|
||||
case LINK_RATE_HIGH2:
|
||||
link_rate_set = 7;
|
||||
break;
|
||||
case LINK_RATE_HIGH3:
|
||||
link_rate_set = 8;
|
||||
break;
|
||||
default:
|
||||
link_rate_set = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (link->dpcd_caps.link_rate_set < link_rate_set)
|
||||
link->dpcd_caps.link_rate_set = link_rate_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
link->verified_link_cap = link->reported_link_cap;
|
||||
}
|
||||
|
||||
|
@ -2621,7 +2716,7 @@ bool dc_link_dp_set_test_pattern(
|
|||
memset(&training_pattern, 0, sizeof(training_pattern));
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream->sink->link == link) {
|
||||
if (pipes[i].stream->link == link) {
|
||||
pipe_ctx = &pipes[i];
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -70,13 +70,12 @@ void dp_enable_link_phy(
|
|||
*/
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream != NULL &&
|
||||
pipes[i].stream->sink != NULL &&
|
||||
pipes[i].stream->sink->link == link) {
|
||||
pipes[i].stream->link == link) {
|
||||
if (pipes[i].clock_source != NULL &&
|
||||
pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
|
||||
pipes[i].clock_source = dp_cs;
|
||||
pipes[i].stream_res.pix_clk_params.requested_pix_clk =
|
||||
pipes[i].stream->timing.pix_clk_khz;
|
||||
pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz =
|
||||
pipes[i].stream->timing.pix_clk_100hz;
|
||||
pipes[i].clock_source->funcs->program_pix_clk(
|
||||
pipes[i].clock_source,
|
||||
&pipes[i].stream_res.pix_clk_params,
|
||||
|
@ -279,10 +278,8 @@ void dp_retrain_link_dp_test(struct dc_link *link,
|
|||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream != NULL &&
|
||||
!pipes[i].top_pipe &&
|
||||
pipes[i].stream->sink != NULL &&
|
||||
pipes[i].stream->sink->link != NULL &&
|
||||
pipes[i].stream_res.stream_enc != NULL &&
|
||||
pipes[i].stream->sink->link == link) {
|
||||
pipes[i].stream->link != NULL &&
|
||||
pipes[i].stream_res.stream_enc != NULL) {
|
||||
udelay(100);
|
||||
|
||||
pipes[i].stream_res.stream_enc->funcs->dp_blank(
|
||||
|
|
|
@ -355,8 +355,8 @@ bool resource_are_streams_timing_synchronizable(
|
|||
!= stream2->timing.v_addressable)
|
||||
return false;
|
||||
|
||||
if (stream1->timing.pix_clk_khz
|
||||
!= stream2->timing.pix_clk_khz)
|
||||
if (stream1->timing.pix_clk_100hz
|
||||
!= stream2->timing.pix_clk_100hz)
|
||||
return false;
|
||||
|
||||
if (stream1->clamping.c_depth != stream2->clamping.c_depth)
|
||||
|
@ -1559,7 +1559,7 @@ static struct stream_encoder *find_first_free_match_stream_enc_for_link(
|
|||
{
|
||||
int i;
|
||||
int j = -1;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
|
||||
for (i = 0; i < pool->stream_enc_count; i++) {
|
||||
if (!res_ctx->is_stream_enc_acquired[i] &&
|
||||
|
@ -1748,7 +1748,7 @@ static struct dc_stream_state *find_pll_sharable_stream(
|
|||
if (resource_are_streams_timing_synchronizable(
|
||||
stream_needs_pll, stream_has_pll)
|
||||
&& !dc_is_dp_signal(stream_has_pll->signal)
|
||||
&& stream_has_pll->sink->link->connector_signal
|
||||
&& stream_has_pll->link->connector_signal
|
||||
!= SIGNAL_TYPE_VIRTUAL)
|
||||
return stream_has_pll;
|
||||
|
||||
|
@ -1759,7 +1759,7 @@ static struct dc_stream_state *find_pll_sharable_stream(
|
|||
|
||||
static int get_norm_pix_clk(const struct dc_crtc_timing *timing)
|
||||
{
|
||||
uint32_t pix_clk = timing->pix_clk_khz;
|
||||
uint32_t pix_clk = timing->pix_clk_100hz;
|
||||
uint32_t normalized_pix_clk = pix_clk;
|
||||
|
||||
if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
|
||||
|
@ -1791,10 +1791,10 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream)
|
|||
/* update actual pixel clock on all streams */
|
||||
if (dc_is_hdmi_signal(stream->signal))
|
||||
stream->phy_pix_clk = get_norm_pix_clk(
|
||||
&stream->timing);
|
||||
&stream->timing) / 10;
|
||||
else
|
||||
stream->phy_pix_clk =
|
||||
stream->timing.pix_clk_khz;
|
||||
stream->timing.pix_clk_100hz / 10;
|
||||
|
||||
if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
|
||||
stream->phy_pix_clk *= 2;
|
||||
|
@ -1842,7 +1842,7 @@ enum dc_status resource_map_pool_resources(
|
|||
&context->res_ctx, pool, stream);
|
||||
|
||||
if (!pipe_ctx->stream_res.stream_enc)
|
||||
return DC_NO_STREAM_ENG_RESOURCE;
|
||||
return DC_NO_STREAM_ENC_RESOURCE;
|
||||
|
||||
update_stream_engine_usage(
|
||||
&context->res_ctx, pool,
|
||||
|
@ -1850,7 +1850,7 @@ enum dc_status resource_map_pool_resources(
|
|||
true);
|
||||
|
||||
/* TODO: Add check if ASIC support and EDID audio */
|
||||
if (!stream->sink->converter_disable_audio &&
|
||||
if (!stream->converter_disable_audio &&
|
||||
dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
|
||||
stream->audio_info.mode_count) {
|
||||
pipe_ctx->stream_res.audio = find_first_free_audio(
|
||||
|
@ -2112,7 +2112,7 @@ static void set_avi_info_frame(
|
|||
itc = true;
|
||||
itc_value = 1;
|
||||
|
||||
support = stream->sink->edid_caps.content_support;
|
||||
support = stream->content_support;
|
||||
|
||||
if (itc) {
|
||||
if (!support.bits.valid_content_type) {
|
||||
|
@ -2151,8 +2151,8 @@ static void set_avi_info_frame(
|
|||
|
||||
/* TODO : We should handle YCC quantization */
|
||||
/* but we do not have matrix calculation */
|
||||
if (stream->sink->edid_caps.qs_bit == 1 &&
|
||||
stream->sink->edid_caps.qy_bit == 1) {
|
||||
if (stream->qs_bit == 1 &&
|
||||
stream->qy_bit == 1) {
|
||||
if (color_space == COLOR_SPACE_SRGB ||
|
||||
color_space == COLOR_SPACE_2020_RGB_FULLRANGE) {
|
||||
hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE;
|
||||
|
@ -2596,7 +2596,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
|
|||
enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
|
||||
{
|
||||
struct dc *core_dc = dc;
|
||||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *link = stream->link;
|
||||
struct timing_generator *tg = core_dc->res_pool->timing_generators[0];
|
||||
enum dc_status res = DC_OK;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue