Merge tag 'amd-drm-next-5.15-2021-08-06' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-5.15-2021-08-06:

amdgpu:
- Aldebaran fixes
- Powergating fix for Renoir
- Switch virtual DCE over to vkms based atomic modesetting
- Misc typo fixes
- PSP handling cleanups
- DC FP cleanups
- RAS fixes
- Wave debug improvements
- Freesync fix
- BACO/BOCO fixes
- Misc fixes

amdkfd:
- Expose gfx version in sysfs
- Aldebaran fixes

radeon:
- Coding style fix
- Typo fixes
- Pageflip fix

UAPI:
- amdkfd: SVM address range query
  Proposed userspace: https://github.com/RadeonOpenCompute/ROCR-Runtime/tree/memory_model_queries

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210806205248.3864-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie 2021-08-11 14:15:26 +10:00
commit 59b9d6baa1
96 changed files with 1612 additions and 1197 deletions

View File

@ -120,7 +120,7 @@ amdgpu-y += \
amdgpu-y += \
dce_v10_0.o \
dce_v11_0.o \
dce_virtual.o
amdgpu_vkms.o
# add GFX block
amdgpu-y += \

View File

@ -916,6 +916,7 @@ struct amdgpu_device {
/* display */
bool enable_virtual_display;
struct amdgpu_vkms_output *amdgpu_vkms_output;
struct amdgpu_mode_info mode_info;
/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
struct work_struct hotplug_work;

View File

@ -1040,7 +1040,7 @@ void amdgpu_acpi_detect(void)
*/
bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)
{
#if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE)
#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_PM_SLEEP)
if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
if (adev->flags & AMD_IS_APU)
return pm_suspend_target_state == PM_SUSPEND_TO_IDLE;

View File

@ -271,7 +271,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv,
uint64_t *size);
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv, bool *table_freed);
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv);
int amdgpu_amdkfd_gpuvm_sync_memory(

View File

@ -1057,7 +1057,8 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
static int update_gpuvm_pte(struct kgd_mem *mem,
struct kfd_mem_attachment *entry,
struct amdgpu_sync *sync)
struct amdgpu_sync *sync,
bool *table_freed)
{
struct amdgpu_bo_va *bo_va = entry->bo_va;
struct amdgpu_device *adev = entry->adev;
@ -1068,7 +1069,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem,
return ret;
/* Update the page tables */
ret = amdgpu_vm_bo_update(adev, bo_va, false);
ret = amdgpu_vm_bo_update(adev, bo_va, false, table_freed);
if (ret) {
pr_err("amdgpu_vm_bo_update failed\n");
return ret;
@ -1080,7 +1081,8 @@ static int update_gpuvm_pte(struct kgd_mem *mem,
static int map_bo_to_gpuvm(struct kgd_mem *mem,
struct kfd_mem_attachment *entry,
struct amdgpu_sync *sync,
bool no_update_pte)
bool no_update_pte,
bool *table_freed)
{
int ret;
@ -1097,7 +1099,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem,
if (no_update_pte)
return 0;
ret = update_gpuvm_pte(mem, entry, sync);
ret = update_gpuvm_pte(mem, entry, sync, table_freed);
if (ret) {
pr_err("update_gpuvm_pte() failed\n");
goto update_gpuvm_pte_failed;
@ -1605,7 +1607,8 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
}
int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
struct kgd_dev *kgd, struct kgd_mem *mem, void *drm_priv)
struct kgd_dev *kgd, struct kgd_mem *mem,
void *drm_priv, bool *table_freed)
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
@ -1693,7 +1696,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
entry->va, entry->va + bo_size, entry);
ret = map_bo_to_gpuvm(mem, entry, ctx.sync,
is_invalid_userptr);
is_invalid_userptr, table_freed);
if (ret) {
pr_err("Failed to map bo to gpuvm\n");
goto out_unreserve;
@ -1717,6 +1720,12 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
true);
ret = unreserve_bo_and_vms(&ctx, false, false);
/* Only apply no TLB flush on Aldebaran to
* workaround regressions on other Asics.
*/
if (table_freed && (adev->asic_type != CHIP_ALDEBARAN))
*table_freed = true;
goto out;
out_unreserve:
@ -2143,7 +2152,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info)
continue;
kfd_mem_dmaunmap_attachment(mem, attachment);
ret = update_gpuvm_pte(mem, attachment, &sync);
ret = update_gpuvm_pte(mem, attachment, &sync, NULL);
if (ret) {
pr_err("%s: update PTE failed\n", __func__);
/* make sure this gets validated again */
@ -2349,7 +2358,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
continue;
kfd_mem_dmaunmap_attachment(mem, attachment);
ret = update_gpuvm_pte(mem, attachment, &sync_obj);
ret = update_gpuvm_pte(mem, attachment, &sync_obj, NULL);
if (ret) {
pr_debug("Memory eviction: update PTE failed. Try again\n");
goto validate_map_fail;

View File

@ -468,6 +468,46 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;
}
/*
* Helper function to query RAS EEPROM address
*
* @adev: amdgpu_device pointer
*
* Return true if vbios supports ras rom address reporting
*/
bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address)
{
struct amdgpu_mode_info *mode_info = &adev->mode_info;
int index;
u16 data_offset, size;
union firmware_info *firmware_info;
u8 frev, crev;
if (i2c_address == NULL)
return false;
*i2c_address = 0;
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
firmwareinfo);
if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
index, &size, &frev, &crev, &data_offset)) {
/* support firmware_info 3.4 + */
if ((frev == 3 && crev >=4) || (frev > 3)) {
firmware_info = (union firmware_info *)
(mode_info->atom_context->bios + data_offset);
*i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;
}
}
if (*i2c_address != 0)
return true;
return false;
}
union smu_info {
struct atom_smu_info_v3_1 v31;
};

View File

@ -36,6 +36,7 @@ int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev);
bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address);
bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev);
bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev);
int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev);

View File

@ -799,7 +799,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false);
r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false, NULL);
if (r)
return r;
@ -810,7 +810,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
bo_va = fpriv->csa_va;
BUG_ON(!bo_va);
r = amdgpu_vm_bo_update(adev, bo_va, false);
r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;
@ -829,7 +829,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (bo_va == NULL)
continue;
r = amdgpu_vm_bo_update(adev, bo_va, false);
r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;

View File

@ -3647,9 +3647,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
fence_driver_init:
/* Fence driver */
r = amdgpu_fence_driver_init(adev);
r = amdgpu_fence_driver_sw_init(adev);
if (r) {
dev_err(adev->dev, "amdgpu_fence_driver_init failed\n");
dev_err(adev->dev, "amdgpu_fence_driver_sw_init failed\n");
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0);
goto failed;
}
@ -3989,7 +3989,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
}
amdgpu_fence_driver_hw_init(adev);
r = amdgpu_device_ip_late_init(adev);
if (r)
return r;

View File

@ -1215,6 +1215,13 @@ static const struct pci_device_id pciidlist[] = {
/* CYAN_SKILLFISH */
{0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
/* BEIGE_GOBY */
{0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
{0, 0, 0}
};
@ -1231,7 +1238,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
int ret, retry = 0;
bool supports_atomic = false;
if (!amdgpu_virtual_display &&
if (amdgpu_virtual_display ||
amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
supports_atomic = true;
@ -1566,6 +1573,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
pci_ignore_hotplug(pdev);
pci_set_power_state(pdev, PCI_D3cold);
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
} else if (amdgpu_device_supports_boco(drm_dev)) {
/* nothing to do */
} else if (amdgpu_device_supports_baco(drm_dev)) {
amdgpu_device_baco_enter(drm_dev);
}

View File

@ -344,7 +344,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
}
/* disable all the possible outputs/crtcs before entering KMS mode */
if (!amdgpu_device_has_dc_support(adev))
if (!amdgpu_device_has_dc_support(adev) && !amdgpu_virtual_display)
drm_helper_disable_unused_functions(adev_to_drm(adev));
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);

View File

@ -498,7 +498,7 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
}
/**
* amdgpu_fence_driver_init - init the fence driver
* amdgpu_fence_driver_sw_init - init the fence driver
* for all possible rings.
*
* @adev: amdgpu device pointer
@ -509,13 +509,13 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
* amdgpu_fence_driver_start_ring().
* Returns 0 for success.
*/
int amdgpu_fence_driver_init(struct amdgpu_device *adev)
int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev)
{
return 0;
}
/**
* amdgpu_fence_driver_fini - tear down the fence driver
* amdgpu_fence_driver_hw_fini - tear down the fence driver
* for all possible rings.
*
* @adev: amdgpu device pointer
@ -531,8 +531,7 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
if (!ring || !ring->fence_drv.initialized)
continue;
if (!ring->no_scheduler)
drm_sched_fini(&ring->sched);
/* You can't wait for HW to signal if it's gone */
if (!drm_dev_is_unplugged(&adev->ddev))
r = amdgpu_fence_wait_empty(ring);
@ -560,6 +559,9 @@ void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev)
if (!ring || !ring->fence_drv.initialized)
continue;
if (!ring->no_scheduler)
drm_sched_fini(&ring->sched);
for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
dma_fence_put(ring->fence_drv.fences[j]);
kfree(ring->fence_drv.fences);

View File

@ -621,7 +621,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
if (operation == AMDGPU_VA_OP_MAP ||
operation == AMDGPU_VA_OP_REPLACE) {
r = amdgpu_vm_bo_update(adev, bo_va, false);
r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
goto error;
}

View File

@ -41,8 +41,6 @@
#include "amdgpu_securedisplay.h"
#include "amdgpu_atomfirmware.h"
#include <drm/drm_drv.h>
static int psp_sysfs_init(struct amdgpu_device *adev);
static void psp_sysfs_fini(struct amdgpu_device *adev);
@ -253,6 +251,12 @@ static int psp_sw_init(void *handle)
struct psp_runtime_boot_cfg_entry boot_cfg_entry;
struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx;
psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!psp->cmd) {
DRM_ERROR("Failed to allocate memory to command buffer!\n");
ret = -ENOMEM;
}
if (!amdgpu_sriov_vf(adev)) {
ret = psp_init_microcode(psp);
if (ret) {
@ -315,25 +319,30 @@ static int psp_sw_init(void *handle)
static int psp_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct psp_context *psp = &adev->psp;
struct psp_gfx_cmd_resp *cmd = psp->cmd;
psp_memory_training_fini(&adev->psp);
if (adev->psp.sos_fw) {
release_firmware(adev->psp.sos_fw);
adev->psp.sos_fw = NULL;
psp_memory_training_fini(psp);
if (psp->sos_fw) {
release_firmware(psp->sos_fw);
psp->sos_fw = NULL;
}
if (adev->psp.asd_fw) {
release_firmware(adev->psp.asd_fw);
adev->psp.asd_fw = NULL;
if (psp->asd_fw) {
release_firmware(psp->asd_fw);
psp->asd_fw = NULL;
}
if (adev->psp.ta_fw) {
release_firmware(adev->psp.ta_fw);
adev->psp.ta_fw = NULL;
if (psp->ta_fw) {
release_firmware(psp->ta_fw);
psp->ta_fw = NULL;
}
if (adev->asic_type == CHIP_NAVI10 ||
adev->asic_type == CHIP_SIENNA_CICHLID)
psp_sysfs_fini(adev);
kfree(cmd);
cmd = NULL;
return 0;
}
@ -417,8 +426,6 @@ psp_cmd_submit_buf(struct psp_context *psp,
if (!drm_dev_enter(&psp->adev->ddev, &idx))
return 0;
mutex_lock(&psp->mutex);
memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE);
memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));
@ -478,11 +485,26 @@ psp_cmd_submit_buf(struct psp_context *psp,
}
exit:
mutex_unlock(&psp->mutex);
drm_dev_exit(idx);
return ret;
}
static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp)
{
struct psp_gfx_cmd_resp *cmd = psp->cmd;
mutex_lock(&psp->mutex);
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
return cmd;
}
void release_psp_cmd_buf(struct psp_context *psp)
{
mutex_unlock(&psp->mutex);
}
static void psp_prep_tmr_cmd_buf(struct psp_context *psp,
struct psp_gfx_cmd_resp *cmd,
uint64_t tmr_mc, struct amdgpu_bo *tmr_bo)
@ -517,11 +539,8 @@ static int psp_load_toc(struct psp_context *psp,
uint32_t *tmr_size)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
/* Copy toc to psp firmware private buffer */
psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
@ -531,7 +550,9 @@ static int psp_load_toc(struct psp_context *psp,
psp->fence_buf_mc_addr);
if (!ret)
*tmr_size = psp->cmd_buf_mem->resp.tmr_size;
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -596,9 +617,7 @@ static int psp_tmr_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo);
DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
@ -607,13 +626,13 @@ static int psp_tmr_load(struct psp_context *psp)
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
struct psp_gfx_cmd_resp *cmd)
struct psp_gfx_cmd_resp *cmd)
{
if (amdgpu_sriov_vf(psp->adev))
cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
@ -624,11 +643,7 @@ static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
static int psp_tmr_unload(struct psp_context *psp)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_unload_cmd_buf(psp, cmd);
DRM_INFO("free PSP TMR buffer\n");
@ -636,7 +651,7 @@ static int psp_tmr_unload(struct psp_context *psp)
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -670,9 +685,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION;
@ -684,7 +697,7 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32);
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -692,13 +705,13 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
{
struct psp_context *psp = &adev->psp;
struct psp_gfx_cmd_resp *cmd = psp->cmd;
struct psp_gfx_cmd_resp *cmd;
int ret;
if (amdgpu_sriov_vf(adev))
return 0;
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET;
@ -709,47 +722,59 @@ static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
(cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0;
}
release_psp_cmd_buf(psp);
return ret;
}
static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg)
{
int ret;
struct psp_context *psp = &adev->psp;
struct psp_gfx_cmd_resp *cmd = psp->cmd;
struct psp_gfx_cmd_resp *cmd;
if (amdgpu_sriov_vf(adev))
return 0;
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET;
cmd->cmd.boot_cfg.boot_config = boot_cfg;
cmd->cmd.boot_cfg.boot_config_valid = boot_cfg;
return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
release_psp_cmd_buf(psp);
return ret;
}
static int psp_rl_load(struct amdgpu_device *adev)
{
int ret;
struct psp_context *psp = &adev->psp;
struct psp_gfx_cmd_resp *cmd = psp->cmd;
struct psp_gfx_cmd_resp *cmd;
if (!is_psp_fw_valid(psp->rl))
return 0;
cmd = acquire_psp_cmd_buf(psp);
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes);
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(psp->fw_pri_mc_addr);
cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr);
cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes;
cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST;
return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
release_psp_cmd_buf(psp);
return ret;
}
static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
@ -777,9 +802,7 @@ static int psp_asd_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev) || !psp->asd_ucode_size)
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_copy_fw(psp, psp->asd_start_addr, psp->asd_ucode_size);
@ -793,7 +816,7 @@ static int psp_asd_load(struct psp_context *psp)
psp->asd_context.session_id = cmd->resp.session_id;
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -816,9 +839,7 @@ static int psp_asd_unload(struct psp_context *psp)
if (!psp->asd_context.asd_initialized)
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id);
@ -827,7 +848,7 @@ static int psp_asd_unload(struct psp_context *psp)
if (!ret)
psp->asd_context.asd_initialized = false;
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -843,22 +864,21 @@ static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd,
int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,
uint32_t value)
{
struct psp_gfx_cmd_resp *cmd = NULL;
struct psp_gfx_cmd_resp *cmd;
int ret = 0;
if (reg >= PSP_REG_LAST)
return -EINVAL;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_reg_prog_cmd_buf(cmd, reg, value);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (ret)
DRM_ERROR("PSP failed to program reg id %d", reg);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -909,18 +929,14 @@ static int psp_ta_invoke(struct psp_context *psp,
uint32_t session_id)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -934,9 +950,7 @@ static int psp_xgmi_load(struct psp_context *psp)
* TODO: bypass the loading in sriov for now
*/
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_copy_fw(psp, psp->ta_xgmi_start_addr, psp->ta_xgmi_ucode_size);
@ -954,7 +968,7 @@ static int psp_xgmi_load(struct psp_context *psp)
psp->xgmi_context.session_id = cmd->resp.session_id;
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -974,16 +988,14 @@ static int psp_xgmi_unload(struct psp_context *psp)
* TODO: bypass the unloading in sriov for now
*/
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1213,10 +1225,6 @@ static int psp_ras_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
psp_copy_fw(psp, psp->ta_ras_start_addr, psp->ta_ras_ucode_size);
ras_cmd = (struct ta_ras_shared_memory *)psp->ras.ras_shared_buf;
@ -1226,6 +1234,8 @@ static int psp_ras_load(struct psp_context *psp)
else
ras_cmd->ras_in_message.init_flags.dgpu_mode = 1;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
psp->ta_ras_ucode_size,
@ -1244,11 +1254,11 @@ static int psp_ras_load(struct psp_context *psp)
dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
}
release_psp_cmd_buf(psp);
if (ret || ras_cmd->ras_status)
amdgpu_ras_fini(psp->adev);
kfree(cmd);
return ret;
}
@ -1263,16 +1273,14 @@ static int psp_ras_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->ras.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1522,13 +1530,11 @@ static int psp_hdcp_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
psp_copy_fw(psp, psp->ta_hdcp_start_addr,
psp->ta_hdcp_ucode_size);
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
psp->ta_hdcp_ucode_size,
@ -1543,7 +1549,7 @@ static int psp_hdcp_load(struct psp_context *psp)
mutex_init(&psp->hdcp_context.mutex);
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1587,15 +1593,13 @@ static int psp_hdcp_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1673,12 +1677,10 @@ static int psp_dtm_load(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
psp_copy_fw(psp, psp->ta_dtm_start_addr, psp->ta_dtm_ucode_size);
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
psp->ta_dtm_ucode_size,
@ -1693,7 +1695,7 @@ static int psp_dtm_load(struct psp_context *psp)
mutex_init(&psp->dtm_context.mutex);
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1738,15 +1740,13 @@ static int psp_dtm_unload(struct psp_context *psp)
if (amdgpu_sriov_vf(psp->adev))
return 0;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1818,12 +1818,10 @@ static int psp_rap_load(struct psp_context *psp)
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
psp_copy_fw(psp, psp->ta_rap_start_addr, psp->ta_rap_ucode_size);
cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_load_cmd_buf(cmd,
psp->fw_pri_mc_addr,
psp->ta_rap_ucode_size,
@ -1838,7 +1836,7 @@ static int psp_rap_load(struct psp_context *psp)
mutex_init(&psp->rap_context.mutex);
}
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1846,17 +1844,13 @@ static int psp_rap_load(struct psp_context *psp)
static int psp_rap_unload(struct psp_context *psp)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -1982,11 +1976,7 @@ static int psp_securedisplay_init_shared_buf(struct psp_context *psp)
static int psp_securedisplay_load(struct psp_context *psp)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
memset(psp->fw_pri_buf, 0, PSP_1_MEG);
memcpy(psp->fw_pri_buf, psp->ta_securedisplay_start_addr, psp->ta_securedisplay_ucode_size);
@ -1999,32 +1989,27 @@ static int psp_securedisplay_load(struct psp_context *psp)
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
if (ret)
goto failed;
if (!ret) {
psp->securedisplay_context.securedisplay_initialized = true;
psp->securedisplay_context.session_id = cmd->resp.session_id;
mutex_init(&psp->securedisplay_context.mutex);
}
psp->securedisplay_context.securedisplay_initialized = true;
psp->securedisplay_context.session_id = cmd->resp.session_id;
mutex_init(&psp->securedisplay_context.mutex);
release_psp_cmd_buf(psp);
failed:
kfree(cmd);
return ret;
}
static int psp_securedisplay_unload(struct psp_context *psp)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.session_id);
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}
@ -2400,8 +2385,6 @@ static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
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);
@ -2418,13 +2401,15 @@ static int psp_execute_non_psp_fw_load(struct psp_context *psp,
struct amdgpu_firmware_info *ucode)
{
int ret = 0;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
ret = psp_prep_load_ip_fw_cmd_buf(ucode, psp->cmd);
if (ret)
return ret;
ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd);
if (!ret) {
ret = psp_cmd_submit_buf(psp, ucode, cmd,
psp->fence_buf_mc_addr);
}
ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
psp->fence_buf_mc_addr);
release_psp_cmd_buf(psp);
return ret;
}
@ -2579,10 +2564,6 @@ static int psp_load_fw(struct amdgpu_device *adev)
goto skip_memalloc;
}
psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!psp->cmd)
return -ENOMEM;
if (amdgpu_sriov_vf(adev)) {
ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
AMDGPU_GEM_DOMAIN_VRAM,
@ -2736,9 +2717,6 @@ static int psp_hw_fini(void *handle)
amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
(void **)&psp->cmd_buf_mem);
kfree(psp->cmd);
psp->cmd = NULL;
return 0;
}
@ -2902,17 +2880,15 @@ int psp_gpu_reset(struct amdgpu_device *adev)
int psp_rlc_autoload_start(struct psp_context *psp)
{
int ret;
struct psp_gfx_cmd_resp *cmd;
cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC;
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
kfree(cmd);
release_psp_cmd_buf(psp);
return ret;
}

View File

@ -54,9 +54,9 @@ enum psp_bootloader_cmd {
PSP_BL__LOAD_SYSDRV = 0x10000,
PSP_BL__LOAD_SOSDRV = 0x20000,
PSP_BL__LOAD_KEY_DATABASE = 0x80000,
PSP_BL__LOAD_SOCDRV = 0x90000,
PSP_BL__LOAD_INTFDRV = 0xA0000,
PSP_BL__LOAD_DBGDRV = 0xB0000,
PSP_BL__LOAD_SOCDRV = 0xB0000,
PSP_BL__LOAD_INTFDRV = 0xC0000,
PSP_BL__LOAD_DBGDRV = 0xD0000,
PSP_BL__DRAM_LONG_TRAIN = 0x100000,
PSP_BL__DRAM_SHORT_TRAIN = 0x200000,
PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000,

View File

@ -27,6 +27,7 @@
#include <linux/bits.h>
#include "atom.h"
#include "amdgpu_eeprom.h"
#include "amdgpu_atomfirmware.h"
#include <linux/debugfs.h>
#include <linux/uaccess.h>
@ -116,6 +117,22 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
if (!control)
return false;
control->i2c_address = 0;
if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)&control->i2c_address))
{
if (control->i2c_address == 0xA0)
control->i2c_address = 0;
else if (control->i2c_address == 0xA8)
control->i2c_address = 0x40000;
else {
dev_warn(adev->dev, "RAS EEPROM I2C address not supported");
return false;
}
return true;
}
switch (adev->asic_type) {
case CHIP_VEGA20:
control->i2c_address = EEPROM_I2C_MADDR_VEGA20;

View File

@ -54,11 +54,12 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
{
struct drm_mm_node *node;
if (!res) {
if (!res || res->mem_type == TTM_PL_SYSTEM) {
cur->start = start;
cur->size = size;
cur->remaining = size;
cur->node = NULL;
WARN_ON(res && start + size > res->num_pages << PAGE_SHIFT);
return;
}

View File

@ -106,7 +106,6 @@ struct amdgpu_fence_driver {
struct dma_fence **fences;
};
int amdgpu_fence_driver_init(struct amdgpu_device *adev);
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
@ -115,9 +114,10 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
struct amdgpu_irq_src *irq_src,
unsigned irq_type);
void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev);
void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev);
void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence,
unsigned flags);
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,

View File

@ -1123,7 +1123,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_device *bdev,
struct amdgpu_ttm_tt *gtt = (void *)ttm;
/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
if (gtt && gtt->userptr) {
if (gtt->userptr) {
ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!ttm->sg)
return -ENOMEM;
@ -1148,7 +1148,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
struct amdgpu_ttm_tt *gtt = (void *)ttm;
struct amdgpu_device *adev;
if (gtt && gtt->userptr) {
if (gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
kfree(ttm->sg);
ttm->sg = NULL;

View File

@ -0,0 +1,643 @@
// SPDX-License-Identifier: GPL-2.0+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include "amdgpu.h"
#ifdef CONFIG_DRM_AMDGPU_SI
#include "dce_v6_0.h"
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "dce_v8_0.h"
#endif
#include "dce_v10_0.h"
#include "dce_v11_0.h"
#include "ivsrcid/ivsrcid_vislands30.h"
#include "amdgpu_vkms.h"
#include "amdgpu_display.h"
/**
* DOC: amdgpu_vkms
*
* The amdgpu vkms interface provides a virtual KMS interface for several use
* cases: devices without display hardware, platforms where the actual display
* hardware is not useful (e.g., servers), SR-IOV virtual functions, device
* emulation/simulation, and device bring up prior to display hardware being
* usable. We previously emulated a legacy KMS interface, but there was a desire
* to move to the atomic KMS interface. The vkms driver did everything we
* needed, but we wanted KMS support natively in the driver without buffer
* sharing and the ability to support an instance of VKMS per device. We first
* looked at splitting vkms into a stub driver and a helper module that other
* drivers could use to implement a virtual display, but this strategy ended up
* being messy due to driver specific callbacks needed for buffer management.
* Ultimately, it proved easier to import the vkms code as it mostly used core
* drm helpers anyway.
*/
static const u32 amdgpu_vkms_formats[] = {
DRM_FORMAT_XRGB8888,
};
static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
{
struct amdgpu_vkms_output *output = container_of(timer,
struct amdgpu_vkms_output,
vblank_hrtimer);
struct drm_crtc *crtc = &output->crtc;
u64 ret_overrun;
bool ret;
ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
output->period_ns);
WARN_ON(ret_overrun != 1);
ret = drm_crtc_handle_vblank(crtc);
if (!ret)
DRM_ERROR("amdgpu_vkms failure on handling vblank");
return HRTIMER_RESTART;
}
static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
unsigned int pipe = drm_crtc_index(crtc);
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
drm_calc_timestamping_constants(crtc, &crtc->mode);
hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;
out->period_ns = ktime_set(0, vblank->framedur_ns);
hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL);
return 0;
}
static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
{
struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc);
hrtimer_cancel(&out->vblank_hrtimer);
}
static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
int *max_error,
ktime_t *vblank_time,
bool in_vblank_irq)
{
struct drm_device *dev = crtc->dev;
unsigned int pipe = crtc->index;
struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
if (!READ_ONCE(vblank->enabled)) {
*vblank_time = ktime_get();
return true;
}
*vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires);
if (WARN_ON(*vblank_time == vblank->time))
return true;
/*
* To prevent races we roll the hrtimer forward before we do any
* interrupt processing - this is how real hw works (the interrupt is
* only generated after all the vblank registers are updated) and what
* the vblank core expects. Therefore we need to always correct the
* timestampe by one frame.
*/
*vblank_time -= output->period_ns;
return true;
}
static const struct drm_crtc_funcs amdgpu_vkms_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = drm_crtc_cleanup,
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.enable_vblank = amdgpu_vkms_enable_vblank,
.disable_vblank = amdgpu_vkms_disable_vblank,
.get_vblank_timestamp = amdgpu_vkms_get_vblank_timestamp,
};
static void amdgpu_vkms_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
drm_crtc_vblank_on(crtc);
}
static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
drm_crtc_vblank_off(crtc);
}
static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
if (crtc->state->event) {
spin_lock(&crtc->dev->event_lock);
if (drm_crtc_vblank_get(crtc) != 0)
drm_crtc_send_vblank_event(crtc, crtc->state->event);
else
drm_crtc_arm_vblank_event(crtc, crtc->state->event);
spin_unlock(&crtc->dev->event_lock);
crtc->state->event = NULL;
}
}
static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {
.atomic_flush = amdgpu_vkms_crtc_atomic_flush,
.atomic_enable = amdgpu_vkms_crtc_atomic_enable,
.atomic_disable = amdgpu_vkms_crtc_atomic_disable,
};
static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
struct drm_plane *primary, struct drm_plane *cursor)
{
int ret;
ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor,
&amdgpu_vkms_crtc_funcs, NULL);
if (ret) {
DRM_ERROR("Failed to init CRTC\n");
return ret;
}
drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs);
return ret;
}
static const struct drm_connector_funcs amdgpu_vkms_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
unsigned i;
static const struct mode_size {
int w;
int h;
} common_modes[] = {
{ 640, 480},
{ 720, 480},
{ 800, 600},
{ 848, 480},
{1024, 768},
{1152, 768},
{1280, 720},
{1280, 800},
{1280, 854},
{1280, 960},
{1280, 1024},
{1440, 900},
{1400, 1050},
{1680, 1050},
{1600, 1200},
{1920, 1080},
{1920, 1200},
{2560, 1440},
{4096, 3112},
{3656, 2664},
{3840, 2160},
{4096, 2160},
};
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
drm_mode_probed_add(connector, mode);
}
drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
return ARRAY_SIZE(common_modes);
}
static const struct drm_connector_helper_funcs amdgpu_vkms_conn_helper_funcs = {
.get_modes = amdgpu_vkms_conn_get_modes,
};
static const struct drm_plane_funcs amdgpu_vkms_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
static void amdgpu_vkms_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *old_state)
{
return;
}
static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
plane);
struct drm_crtc_state *crtc_state;
int ret;
if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
return 0;
crtc_state = drm_atomic_get_crtc_state(state,
new_plane_state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
false, true);
if (ret != 0)
return ret;
/* for now primary plane must be visible and full screen */
if (!new_plane_state->visible)
return -EINVAL;
return 0;
}
static int amdgpu_vkms_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *new_state)
{
struct amdgpu_framebuffer *afb;
struct drm_gem_object *obj;
struct amdgpu_device *adev;
struct amdgpu_bo *rbo;
struct list_head list;
struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket;
uint32_t domain;
int r;
if (!new_state->fb) {
DRM_DEBUG_KMS("No FB bound\n");
return 0;
}
afb = to_amdgpu_framebuffer(new_state->fb);
obj = new_state->fb->obj[0];
rbo = gem_to_amdgpu_bo(obj);
adev = amdgpu_ttm_adev(rbo->tbo.bdev);
INIT_LIST_HEAD(&list);
tv.bo = &rbo->tbo;
tv.num_shared = 1;
list_add(&tv.head, &list);
r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
if (r) {
dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
return r;
}
if (plane->type != DRM_PLANE_TYPE_CURSOR)
domain = amdgpu_display_supported_domains(adev, rbo->flags);
else
domain = AMDGPU_GEM_DOMAIN_VRAM;
r = amdgpu_bo_pin(rbo, domain);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS)
DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
ttm_eu_backoff_reservation(&ticket, &list);
return r;
}
r = amdgpu_ttm_alloc_gart(&rbo->tbo);
if (unlikely(r != 0)) {
amdgpu_bo_unpin(rbo);
ttm_eu_backoff_reservation(&ticket, &list);
DRM_ERROR("%p bind failed\n", rbo);
return r;
}
ttm_eu_backoff_reservation(&ticket, &list);
afb->address = amdgpu_bo_gpu_offset(rbo);
amdgpu_bo_ref(rbo);
return 0;
}
static void amdgpu_vkms_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct amdgpu_bo *rbo;
int r;
if (!old_state->fb)
return;
rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
r = amdgpu_bo_reserve(rbo, false);
if (unlikely(r)) {
DRM_ERROR("failed to reserve rbo before unpin\n");
return;
}
amdgpu_bo_unpin(rbo);
amdgpu_bo_unreserve(rbo);
amdgpu_bo_unref(&rbo);
}
static const struct drm_plane_helper_funcs amdgpu_vkms_primary_helper_funcs = {
.atomic_update = amdgpu_vkms_plane_atomic_update,
.atomic_check = amdgpu_vkms_plane_atomic_check,
.prepare_fb = amdgpu_vkms_prepare_fb,
.cleanup_fb = amdgpu_vkms_cleanup_fb,
};
static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,
enum drm_plane_type type,
int index)
{
struct drm_plane *plane;
int ret;
plane = kzalloc(sizeof(*plane), GFP_KERNEL);
if (!plane)
return ERR_PTR(-ENOMEM);
ret = drm_universal_plane_init(dev, plane, 1 << index,
&amdgpu_vkms_plane_funcs,
amdgpu_vkms_formats,
ARRAY_SIZE(amdgpu_vkms_formats),
NULL, type, NULL);
if (ret) {
kfree(plane);
return ERR_PTR(ret);
}
drm_plane_helper_add(plane, &amdgpu_vkms_primary_helper_funcs);
return plane;
}
int amdgpu_vkms_output_init(struct drm_device *dev,
struct amdgpu_vkms_output *output, int index)
{
struct drm_connector *connector = &output->connector;
struct drm_encoder *encoder = &output->encoder;
struct drm_crtc *crtc = &output->crtc;
struct drm_plane *primary, *cursor = NULL;
int ret;
primary = amdgpu_vkms_plane_init(dev, DRM_PLANE_TYPE_PRIMARY, index);
if (IS_ERR(primary))
return PTR_ERR(primary);
ret = amdgpu_vkms_crtc_init(dev, crtc, primary, cursor);
if (ret)
goto err_crtc;
ret = drm_connector_init(dev, connector, &amdgpu_vkms_connector_funcs,
DRM_MODE_CONNECTOR_VIRTUAL);
if (ret) {
DRM_ERROR("Failed to init connector\n");
goto err_connector;
}
drm_connector_helper_add(connector, &amdgpu_vkms_conn_helper_funcs);
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
if (ret) {
DRM_ERROR("Failed to init encoder\n");
goto err_encoder;
}
encoder->possible_crtcs = 1 << index;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
DRM_ERROR("Failed to attach connector to encoder\n");
goto err_attach;
}
drm_mode_config_reset(dev);
return 0;
err_attach:
drm_encoder_cleanup(encoder);
err_encoder:
drm_connector_cleanup(connector);
err_connector:
drm_crtc_cleanup(crtc);
err_crtc:
drm_plane_cleanup(primary);
return ret;
}
const struct drm_mode_config_funcs amdgpu_vkms_mode_funcs = {
.fb_create = amdgpu_display_user_framebuffer_create,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
static int amdgpu_vkms_sw_init(void *handle)
{
int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
adev_to_drm(adev)->max_vblank_count = 0;
adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs;
adev_to_drm(adev)->mode_config.max_width = XRES_MAX;
adev_to_drm(adev)->mode_config.max_height = YRES_MAX;
adev_to_drm(adev)->mode_config.preferred_depth = 24;
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
r = amdgpu_display_modeset_create_props(adev);
if (r)
return r;
adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc, sizeof(struct amdgpu_vkms_output), GFP_KERNEL);
if (!adev->amdgpu_vkms_output)
return -ENOMEM;
/* allocate crtcs, encoders, connectors */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i);
if (r)
return r;
}
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
return 0;
}
static int amdgpu_vkms_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i = 0;
for (i = 0; i < adev->mode_info.num_crtc; i++)
if (adev->mode_info.crtcs[i])
hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
kfree(adev->mode_info.bios_hardcoded_edid);
kfree(adev->amdgpu_vkms_output);
drm_kms_helper_poll_fini(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = false;
return 0;
}
static int amdgpu_vkms_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
switch (adev->asic_type) {
#ifdef CONFIG_DRM_AMDGPU_SI
case CHIP_TAHITI:
case CHIP_PITCAIRN:
case CHIP_VERDE:
case CHIP_OLAND:
dce_v6_0_disable_dce(adev);
break;
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
dce_v8_0_disable_dce(adev);
break;
#endif
case CHIP_FIJI:
case CHIP_TONGA:
dce_v10_0_disable_dce(adev);
break;
case CHIP_CARRIZO:
case CHIP_STONEY:
case CHIP_POLARIS10:
case CHIP_POLARIS11:
case CHIP_VEGAM:
dce_v11_0_disable_dce(adev);
break;
case CHIP_TOPAZ:
#ifdef CONFIG_DRM_AMDGPU_SI
case CHIP_HAINAN:
#endif
/* no DCE */
break;
default:
break;
}
return 0;
}
static int amdgpu_vkms_hw_fini(void *handle)
{
return 0;
}
static int amdgpu_vkms_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
r = drm_mode_config_helper_suspend(adev_to_drm(adev));
if (r)
return r;
return amdgpu_vkms_hw_fini(handle);
}
static int amdgpu_vkms_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
r = amdgpu_vkms_hw_init(handle);
if (r)
return r;
return drm_mode_config_helper_resume(adev_to_drm(adev));
}
static bool amdgpu_vkms_is_idle(void *handle)
{
return true;
}
static int amdgpu_vkms_wait_for_idle(void *handle)
{
return 0;
}
static int amdgpu_vkms_soft_reset(void *handle)
{
return 0;
}
static int amdgpu_vkms_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
return 0;
}
static int amdgpu_vkms_set_powergating_state(void *handle,
enum amd_powergating_state state)
{
return 0;
}
static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = {
.name = "amdgpu_vkms",
.early_init = NULL,
.late_init = NULL,
.sw_init = amdgpu_vkms_sw_init,
.sw_fini = amdgpu_vkms_sw_fini,
.hw_init = amdgpu_vkms_hw_init,
.hw_fini = amdgpu_vkms_hw_fini,
.suspend = amdgpu_vkms_suspend,
.resume = amdgpu_vkms_resume,
.is_idle = amdgpu_vkms_is_idle,
.wait_for_idle = amdgpu_vkms_wait_for_idle,
.soft_reset = amdgpu_vkms_soft_reset,
.set_clockgating_state = amdgpu_vkms_set_clockgating_state,
.set_powergating_state = amdgpu_vkms_set_powergating_state,
};
const struct amdgpu_ip_block_version amdgpu_vkms_ip_block =
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &amdgpu_vkms_ip_funcs,
};

View File

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _AMDGPU_VKMS_H_
#define _AMDGPU_VKMS_H_
#define XRES_DEF 1024
#define YRES_DEF 768
#define XRES_MAX 16384
#define YRES_MAX 16384
#define drm_crtc_to_amdgpu_vkms_output(target) \
container_of(target, struct amdgpu_vkms_output, crtc)
extern const struct amdgpu_ip_block_version amdgpu_vkms_ip_block;
struct amdgpu_vkms_output {
struct drm_crtc crtc;
struct drm_encoder encoder;
struct drm_connector connector;
struct hrtimer vblank_hrtimer;
ktime_t period_ns;
struct drm_pending_vblank_event *event;
};
#endif /* _AMDGPU_VKMS_H_ */

View File

@ -1798,7 +1798,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
r = vm->update_funcs->commit(&params, fence);
if (table_freed)
*table_freed = params.table_freed;
*table_freed = *table_freed || params.table_freed;
error_unlock:
amdgpu_vm_eviction_unlock(vm);
@ -1856,6 +1856,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
* @adev: amdgpu_device pointer
* @bo_va: requested BO and VM object
* @clear: if true clear the entries
* @table_freed: return true if page table is freed
*
* Fill in the page table entries for @bo_va.
*
@ -1863,7 +1864,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem,
* 0 for success, -EINVAL for failure.
*/
int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
bool clear)
bool clear, bool *table_freed)
{
struct amdgpu_bo *bo = bo_va->base.bo;
struct amdgpu_vm *vm = bo_va->base.vm;
@ -1942,7 +1943,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
resv, mapping->start,
mapping->last, update_flags,
mapping->offset, mem,
pages_addr, last_update, NULL);
pages_addr, last_update, table_freed);
if (r)
return r;
}
@ -2194,7 +2195,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) {
/* Per VM BOs never need to bo cleared in the page tables */
r = amdgpu_vm_bo_update(adev, bo_va, false);
r = amdgpu_vm_bo_update(adev, bo_va, false, NULL);
if (r)
return r;
}
@ -2213,7 +2214,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
else
clear = true;
r = amdgpu_vm_bo_update(adev, bo_va, clear);
r = amdgpu_vm_bo_update(adev, bo_va, clear, NULL);
if (r)
return r;

View File

@ -408,7 +408,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
struct dma_fence **fence, bool *free_table);
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va,
bool clear);
bool clear, bool *table_freed);
bool amdgpu_vm_evictable(struct amdgpu_bo *bo);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
struct amdgpu_bo *bo, bool evicted);

View File

@ -70,7 +70,7 @@
#include "amdgpu_dm.h"
#include "amdgpu_amdkfd.h"
#include "dce_virtual.h"
#include "amdgpu_vkms.h"
static const struct amdgpu_video_codec_info cik_video_codecs_encode_array[] =
{
@ -2259,7 +2259,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2277,7 +2277,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2295,7 +2295,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2315,7 +2315,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);

View File

@ -1,780 +0,0 @@
/*
* Copyright 2014 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <drm/drm_vblank.h>
#include "amdgpu.h"
#include "amdgpu_pm.h"
#include "amdgpu_i2c.h"
#include "atom.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
#ifdef CONFIG_DRM_AMDGPU_SI
#include "dce_v6_0.h"
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "dce_v8_0.h"
#endif
#include "dce_v10_0.h"
#include "dce_v11_0.h"
#include "dce_virtual.h"
#include "ivsrcid/ivsrcid_vislands30.h"
#include "amdgpu_display.h"
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
int index);
static int dce_virtual_pageflip(struct amdgpu_device *adev,
unsigned crtc_id);
static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer);
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
int crtc,
enum amdgpu_interrupt_state state);
static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
{
return 0;
}
static void dce_virtual_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base, bool async)
{
return;
}
static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
u32 *vbl, u32 *position)
{
*vbl = 0;
*position = 0;
return -EINVAL;
}
static bool dce_virtual_hpd_sense(struct amdgpu_device *adev,
enum amdgpu_hpd_id hpd)
{
return true;
}
static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev,
enum amdgpu_hpd_id hpd)
{
return;
}
static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
{
return 0;
}
/**
* dce_virtual_bandwidth_update - program display watermarks
*
* @adev: amdgpu_device pointer
*
* Calculate and program the display watermarks and line
* buffer allocation (CIK).
*/
static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
{
return;
}
static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
return 0;
}
static void dce_virtual_crtc_destroy(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
drm_crtc_cleanup(crtc);
kfree(amdgpu_crtc);
}
static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
.cursor_set2 = NULL,
.cursor_move = NULL,
.gamma_set = dce_virtual_crtc_gamma_set,
.set_config = amdgpu_display_crtc_set_config,
.destroy = dce_virtual_crtc_destroy,
.page_flip_target = amdgpu_display_crtc_page_flip_target,
.get_vblank_counter = amdgpu_get_vblank_counter_kms,
.enable_vblank = amdgpu_enable_vblank_kms,
.disable_vblank = amdgpu_disable_vblank_kms,
.get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
};
static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
unsigned type;
switch (mode) {
case DRM_MODE_DPMS_ON:
amdgpu_crtc->enabled = true;
/* Make sure VBLANK interrupts are still enabled */
type = amdgpu_display_crtc_idx_to_irq_type(adev,
amdgpu_crtc->crtc_id);
amdgpu_irq_update(adev, &adev->crtc_irq, type);
drm_crtc_vblank_on(crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
drm_crtc_vblank_off(crtc);
amdgpu_crtc->enabled = false;
break;
}
}
static void dce_virtual_crtc_prepare(struct drm_crtc *crtc)
{
dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}
static void dce_virtual_crtc_commit(struct drm_crtc *crtc)
{
dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
struct drm_device *dev = crtc->dev;
if (dev->num_crtcs)
drm_crtc_vblank_off(crtc);
amdgpu_crtc->enabled = false;
amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
amdgpu_crtc->encoder = NULL;
amdgpu_crtc->connector = NULL;
}
static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y, struct drm_framebuffer *old_fb)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
/* update the hw version fpr dpm */
amdgpu_crtc->hw_mode = *adjusted_mode;
return 0;
}
static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
return 0;
}
static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int x, int y, enum mode_set_atomic state)
{
return 0;
}
static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
.dpms = dce_virtual_crtc_dpms,
.mode_fixup = dce_virtual_crtc_mode_fixup,
.mode_set = dce_virtual_crtc_mode_set,
.mode_set_base = dce_virtual_crtc_set_base,
.mode_set_base_atomic = dce_virtual_crtc_set_base_atomic,
.prepare = dce_virtual_crtc_prepare,
.commit = dce_virtual_crtc_commit,
.disable = dce_virtual_crtc_disable,
.get_scanout_position = amdgpu_crtc_get_scanout_position,
};
static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
{
struct amdgpu_crtc *amdgpu_crtc;
amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
(AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
if (amdgpu_crtc == NULL)
return -ENOMEM;
drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs);
drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
amdgpu_crtc->crtc_id = index;
adev->mode_info.crtcs[index] = amdgpu_crtc;
amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
amdgpu_crtc->encoder = NULL;
amdgpu_crtc->connector = NULL;
amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD);
amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle;
hrtimer_start(&amdgpu_crtc->vblank_timer,
DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
return 0;
}
static int dce_virtual_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
dce_virtual_set_display_funcs(adev);
dce_virtual_set_irq_funcs(adev);
adev->mode_info.num_hpd = 1;
adev->mode_info.num_dig = 1;
return 0;
}
static struct drm_encoder *
dce_virtual_encoder(struct drm_connector *connector)
{
struct drm_encoder *encoder;
drm_connector_for_each_possible_encoder(connector, encoder) {
if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
return encoder;
}
/* pick the first one */
drm_connector_for_each_possible_encoder(connector, encoder)
return encoder;
return NULL;
}
static int dce_virtual_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode = NULL;
unsigned i;
static const struct mode_size {
int w;
int h;
} common_modes[] = {
{ 640, 480},
{ 720, 480},
{ 800, 600},
{ 848, 480},
{1024, 768},
{1152, 768},
{1280, 720},
{1280, 800},
{1280, 854},
{1280, 960},
{1280, 1024},
{1440, 900},
{1400, 1050},
{1680, 1050},
{1600, 1200},
{1920, 1080},
{1920, 1200},
{2560, 1440},
{4096, 3112},
{3656, 2664},
{3840, 2160},
{4096, 2160},
};
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
drm_mode_probed_add(connector, mode);
}
return 0;
}
static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
static int
dce_virtual_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static int
dce_virtual_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val)
{
return 0;
}
static void dce_virtual_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
static void dce_virtual_force(struct drm_connector *connector)
{
return;
}
static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
.get_modes = dce_virtual_get_modes,
.mode_valid = dce_virtual_mode_valid,
.best_encoder = dce_virtual_encoder,
};
static const struct drm_connector_funcs dce_virtual_connector_funcs = {
.dpms = dce_virtual_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = dce_virtual_set_property,
.destroy = dce_virtual_destroy,
.force = dce_virtual_force,
};
static int dce_virtual_sw_init(void *handle)
{
int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
if (r)
return r;
adev_to_drm(adev)->max_vblank_count = 0;
adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs;
adev_to_drm(adev)->mode_config.max_width = 16384;
adev_to_drm(adev)->mode_config.max_height = 16384;
adev_to_drm(adev)->mode_config.preferred_depth = 24;
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
r = amdgpu_display_modeset_create_props(adev);
if (r)
return r;
adev_to_drm(adev)->mode_config.max_width = 16384;
adev_to_drm(adev)->mode_config.max_height = 16384;
/* allocate crtcs, encoders, connectors */
for (i = 0; i < adev->mode_info.num_crtc; i++) {
r = dce_virtual_crtc_init(adev, i);
if (r)
return r;
r = dce_virtual_connector_encoder_init(adev, i);
if (r)
return r;
}
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
return 0;
}
static int dce_virtual_sw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int i = 0;
for (i = 0; i < adev->mode_info.num_crtc; i++)
if (adev->mode_info.crtcs[i])
hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);
kfree(adev->mode_info.bios_hardcoded_edid);
drm_kms_helper_poll_fini(adev_to_drm(adev));
drm_mode_config_cleanup(adev_to_drm(adev));
/* clear crtcs pointer to avoid dce irq finish routine access freed data */
memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
adev->mode_info.mode_config_initialized = false;
return 0;
}
static int dce_virtual_hw_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
switch (adev->asic_type) {
#ifdef CONFIG_DRM_AMDGPU_SI
case CHIP_TAHITI:
case CHIP_PITCAIRN:
case CHIP_VERDE:
case CHIP_OLAND:
dce_v6_0_disable_dce(adev);
break;
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
dce_v8_0_disable_dce(adev);
break;
#endif
case CHIP_FIJI:
case CHIP_TONGA:
dce_v10_0_disable_dce(adev);
break;
case CHIP_CARRIZO:
case CHIP_STONEY:
case CHIP_POLARIS10:
case CHIP_POLARIS11:
case CHIP_VEGAM:
dce_v11_0_disable_dce(adev);
break;
case CHIP_TOPAZ:
#ifdef CONFIG_DRM_AMDGPU_SI
case CHIP_HAINAN:
#endif
/* no DCE */
break;
default:
break;
}
return 0;
}
static int dce_virtual_hw_fini(void *handle)
{
return 0;
}
static int dce_virtual_suspend(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
r = amdgpu_display_suspend_helper(adev);
if (r)
return r;
return dce_virtual_hw_fini(handle);
}
static int dce_virtual_resume(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
r = dce_virtual_hw_init(handle);
if (r)
return r;
return amdgpu_display_resume_helper(adev);
}
static bool dce_virtual_is_idle(void *handle)
{
return true;
}
static int dce_virtual_wait_for_idle(void *handle)
{
return 0;
}
static int dce_virtual_soft_reset(void *handle)
{
return 0;
}
static int dce_virtual_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
return 0;
}
static int dce_virtual_set_powergating_state(void *handle,
enum amd_powergating_state state)
{
return 0;
}
static const struct amd_ip_funcs dce_virtual_ip_funcs = {
.name = "dce_virtual",
.early_init = dce_virtual_early_init,
.late_init = NULL,
.sw_init = dce_virtual_sw_init,
.sw_fini = dce_virtual_sw_fini,
.hw_init = dce_virtual_hw_init,
.hw_fini = dce_virtual_hw_fini,
.suspend = dce_virtual_suspend,
.resume = dce_virtual_resume,
.is_idle = dce_virtual_is_idle,
.wait_for_idle = dce_virtual_wait_for_idle,
.soft_reset = dce_virtual_soft_reset,
.set_clockgating_state = dce_virtual_set_clockgating_state,
.set_powergating_state = dce_virtual_set_powergating_state,
};
/* these are handled by the primary encoders */
static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
{
return;
}
static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
{
return;
}
static void
dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return;
}
static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
{
return;
}
static void
dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
{
return;
}
static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
.dpms = dce_virtual_encoder_dpms,
.mode_fixup = dce_virtual_encoder_mode_fixup,
.prepare = dce_virtual_encoder_prepare,
.mode_set = dce_virtual_encoder_mode_set,
.commit = dce_virtual_encoder_commit,
.disable = dce_virtual_encoder_disable,
};
static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
kfree(encoder);
}
static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
.destroy = dce_virtual_encoder_destroy,
};
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
int index)
{
struct drm_encoder *encoder;
struct drm_connector *connector;
/* add a new encoder */
encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
if (!encoder)
return -ENOMEM;
encoder->possible_crtcs = 1 << index;
drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs,
DRM_MODE_ENCODER_VIRTUAL, NULL);
drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
if (!connector) {
kfree(encoder);
return -ENOMEM;
}
/* add a new connector */
drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs,
DRM_MODE_CONNECTOR_VIRTUAL);
drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
/* link them */
drm_connector_attach_encoder(connector, encoder);
return 0;
}
static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
.bandwidth_update = &dce_virtual_bandwidth_update,
.vblank_get_counter = &dce_virtual_vblank_get_counter,
.backlight_set_level = NULL,
.backlight_get_level = NULL,
.hpd_sense = &dce_virtual_hpd_sense,
.hpd_set_polarity = &dce_virtual_hpd_set_polarity,
.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
.page_flip = &dce_virtual_page_flip,
.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
.add_encoder = NULL,
.add_connector = NULL,
};
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
{
adev->mode_info.funcs = &dce_virtual_display_funcs;
}
static int dce_virtual_pageflip(struct amdgpu_device *adev,
unsigned crtc_id)
{
unsigned long flags;
struct amdgpu_crtc *amdgpu_crtc;
struct amdgpu_flip_work *works;
amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
if (crtc_id >= adev->mode_info.num_crtc) {
DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
return -EINVAL;
}
/* IRQ could occur when in initial stage */
if (amdgpu_crtc == NULL)
return 0;
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
works = amdgpu_crtc->pflip_works;
if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
"AMDGPU_FLIP_SUBMITTED(%d)\n",
amdgpu_crtc->pflip_status,
AMDGPU_FLIP_SUBMITTED);
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
return 0;
}
/* page flip completed. clean up */
amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
amdgpu_crtc->pflip_works = NULL;
/* wakeup usersapce */
if (works->event)
drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
drm_crtc_vblank_put(&amdgpu_crtc->base);
amdgpu_bo_unref(&works->old_abo);
kfree(works->shared);
kfree(works);
return 0;
}
static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
{
struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
struct amdgpu_crtc, vblank_timer);
struct drm_device *ddev = amdgpu_crtc->base.dev;
struct amdgpu_device *adev = drm_to_adev(ddev);
struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources
[VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER];
int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev,
amdgpu_crtc->crtc_id);
if (amdgpu_irq_enabled(adev, source, irq_type)) {
drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
}
hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
int crtc,
enum amdgpu_interrupt_state state)
{
if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
DRM_DEBUG("invalid crtc %d\n", crtc);
return;
}
adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
}
static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
unsigned type,
enum amdgpu_interrupt_state state)
{
if (type > AMDGPU_CRTC_IRQ_VBLANK6)
return -EINVAL;
dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
return 0;
}
static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
.set = dce_virtual_set_crtc_irq_state,
.process = NULL,
};
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
{
adev->crtc_irq.num_types = adev->mode_info.num_crtc;
adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
}
const struct amdgpu_ip_block_version dce_virtual_ip_block =
{
.type = AMD_IP_BLOCK_TYPE_DCE,
.major = 1,
.minor = 0,
.rev = 0,
.funcs = &dce_virtual_ip_funcs,
};

View File

@ -4621,6 +4621,7 @@ static void gfx_v10_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd,
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2);
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1);
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_M0);
dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE);
}
static void gfx_v10_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,

View File

@ -3027,6 +3027,7 @@ static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,

View File

@ -4198,6 +4198,7 @@ static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,

View File

@ -5279,6 +5279,7 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,

View File

@ -1295,6 +1295,16 @@ static bool is_raven_kicker(struct amdgpu_device *adev)
return false;
}
static bool check_if_enlarge_doorbell_range(struct amdgpu_device *adev)
{
if ((adev->asic_type == CHIP_RENOIR) &&
(adev->gfx.me_fw_version >= 0x000000a5) &&
(adev->gfx.me_feature_version >= 52))
return true;
else
return false;
}
static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
{
if (gfx_v9_0_should_disable_gfxoff(adev->pdev))
@ -2080,6 +2090,7 @@ static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_MODE);
}
static void gfx_v9_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
@ -3675,7 +3686,16 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring)
if (ring->use_doorbell) {
WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER,
(adev->doorbell_index.kiq * 2) << 2);
WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
/* If GC has entered CGPG, ringing doorbell > first page
* doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to
* workaround this issue. And this change has to align with firmware
* update.
*/
if (check_if_enlarge_doorbell_range(adev))
WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
(adev->doorbell.size - 4));
else
WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
(adev->doorbell_index.userqueue_end * 2) << 2);
}

View File

@ -1171,8 +1171,8 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
break;
case CHIP_ALDEBARAN:
adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM;
adev->umc.channel_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
adev->umc.umc_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET;
if (!adev->gmc.xgmi.connected_to_cpu)
adev->umc.ras_funcs = &umc_v6_7_ras_funcs;

View File

@ -58,7 +58,7 @@
#include "jpeg_v2_0.h"
#include "vcn_v3_0.h"
#include "jpeg_v3_0.h"
#include "dce_virtual.h"
#include "amdgpu_vkms.h"
#include "mes_v10_1.h"
#include "mxgpu_nv.h"
#include "smuio_v11_0.h"
@ -721,7 +721,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -749,7 +749,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -779,7 +779,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -802,7 +802,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -823,7 +823,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -843,7 +843,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
is_support_sw_smu(adev))
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -865,7 +865,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -883,11 +883,11 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -905,7 +905,7 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v5_0_ip_block);
break;

View File

@ -44,7 +44,7 @@
#include "dce_v6_0.h"
#include "si.h"
#include "uvd_v3_1.h"
#include "dce_virtual.h"
#include "amdgpu_vkms.h"
#include "gca/gfx_6_0_d.h"
#include "oss/oss_1_0_d.h"
#include "oss/oss_1_0_sh_mask.h"
@ -2759,7 +2759,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2777,7 +2777,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2795,7 +2795,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
break;
default:
BUG();

View File

@ -74,7 +74,7 @@
#include "smuio_v9_0.h"
#include "smuio_v11_0.h"
#include "smuio_v13_0.h"
#include "dce_virtual.h"
#include "amdgpu_vkms.h"
#include "mxgpu_ai.h"
#include "amdgpu_ras.h"
#include "amdgpu_xgmi.h"
@ -843,7 +843,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -863,7 +863,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -885,7 +885,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
}
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
@ -909,7 +909,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);

View File

@ -30,17 +30,17 @@
const uint32_t
umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
{28, 12, 6, 22}, {19, 3, 9, 25},
{20, 4, 30, 14}, {11, 27, 1, 17},
{24, 8, 2, 18}, {15, 31, 5, 21},
{16, 0, 26, 10}, {7, 23, 29, 13}
{28, 20, 24, 16, 12, 4, 8, 0},
{6, 30, 2, 26, 22, 14, 18, 10},
{19, 11, 15, 7, 3, 27, 31, 23},
{9, 1, 5, 29, 25, 17, 21, 13}
};
const uint32_t
umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM] = {
{19, 3, 9, 25}, {28, 12, 6, 22},
{11, 27, 1, 17}, {20, 4, 30, 14},
{15, 31, 5, 21}, {24, 8, 2, 18},
{7, 23, 29, 13}, {16, 0, 26, 10}
{19, 11, 15, 7, 3, 27, 31, 23},
{9, 1, 5, 29, 25, 17, 21, 13},
{28, 20, 24, 16, 12, 4, 8, 0},
{6, 30, 2, 26, 22, 14, 18, 10},
};
static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev,

View File

@ -36,9 +36,9 @@
#define UMC_V6_7_INST_DIST 0x40000
/* number of umc channel instance with memory map register access */
#define UMC_V6_7_CHANNEL_INSTANCE_NUM 4
#define UMC_V6_7_UMC_INSTANCE_NUM 4
/* number of umc instance with memory map register access */
#define UMC_V6_7_UMC_INSTANCE_NUM 8
#define UMC_V6_7_CHANNEL_INSTANCE_NUM 8
/* total channel instances in one umc block */
#define UMC_V6_7_TOTAL_CHANNEL_NUM (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM)
/* UMC regiser per channel offset */

View File

@ -90,9 +90,7 @@ static int vcn_v3_0_early_init(void *handle)
int i;
if (amdgpu_sriov_vf(adev)) {
for (i = 0; i < VCN_INSTANCES_SIENNA_CICHLID; i++)
if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i))
adev->vcn.num_vcn_inst++;
adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID;
adev->vcn.harvest_config = 0;
adev->vcn.num_enc_rings = 1;
@ -153,8 +151,7 @@ static int vcn_v3_0_sw_init(void *handle)
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);
if ((adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) ||
(amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)) {
if (adev->vcn.num_vcn_inst == VCN_INSTANCES_SIENNA_CICHLID) {
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].ucode_id = AMDGPU_UCODE_ID_VCN1;
adev->firmware.ucode[AMDGPU_UCODE_ID_VCN1].fw = adev->vcn.fw;
adev->firmware.fw_size +=
@ -328,17 +325,27 @@ static int vcn_v3_0_hw_init(void *handle)
continue;
ring = &adev->vcn.inst[i].ring_dec;
ring->wptr = 0;
ring->wptr_old = 0;
vcn_v3_0_dec_ring_set_wptr(ring);
ring->sched.ready = true;
if (amdgpu_vcn_is_disabled_vcn(adev, VCN_DECODE_RING, i)) {
ring->sched.ready = false;
dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name);
} else {
ring->wptr = 0;
ring->wptr_old = 0;
vcn_v3_0_dec_ring_set_wptr(ring);
ring->sched.ready = true;
}
for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
ring = &adev->vcn.inst[i].ring_enc[j];
ring->wptr = 0;
ring->wptr_old = 0;
vcn_v3_0_enc_ring_set_wptr(ring);
ring->sched.ready = true;
if (amdgpu_vcn_is_disabled_vcn(adev, VCN_ENCODE_RING, i)) {
ring->sched.ready = false;
dev_info(adev->dev, "ring %s is disabled by hypervisor\n", ring->name);
} else {
ring->wptr = 0;
ring->wptr_old = 0;
vcn_v3_0_enc_ring_set_wptr(ring);
ring->sched.ready = true;
}
}
}
} else {

View File

@ -77,7 +77,7 @@
#if defined(CONFIG_DRM_AMD_ACP)
#include "amdgpu_acp.h"
#endif
#include "dce_virtual.h"
#include "amdgpu_vkms.h"
#include "mxgpu_vi.h"
#include "amdgpu_dm.h"
@ -2102,7 +2102,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v2_4_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
break;
case CHIP_FIJI:
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
@ -2112,7 +2112,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2132,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2155,7 +2155,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_1_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2173,7 +2173,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);
@ -2194,7 +2194,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &sdma_v3_0_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);
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
amdgpu_device_ip_block_add(adev, &dm_ip_block);

View File

@ -1393,6 +1393,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
long err = 0;
int i;
uint32_t *devices_arr = NULL;
bool table_freed = false;
dev = kfd_device_by_id(GET_GPU_ID(args->handle));
if (!dev)
@ -1450,7 +1451,8 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
goto get_mem_obj_from_handle_failed;
}
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
peer->kgd, (struct kgd_mem *)mem, peer_pdd->drm_priv);
peer->kgd, (struct kgd_mem *)mem,
peer_pdd->drm_priv, &table_freed);
if (err) {
pr_err("Failed to map to gpu %d/%d\n",
i, args->n_devices);
@ -1468,16 +1470,17 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
}
/* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) {
peer = kfd_device_by_id(devices_arr[i]);
if (WARN_ON_ONCE(!peer))
continue;
peer_pdd = kfd_get_process_device_data(peer, p);
if (WARN_ON_ONCE(!peer_pdd))
continue;
kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
if (table_freed) {
for (i = 0; i < args->n_devices; i++) {
peer = kfd_device_by_id(devices_arr[i]);
if (WARN_ON_ONCE(!peer))
continue;
peer_pdd = kfd_get_process_device_data(peer, p);
if (WARN_ON_ONCE(!peer_pdd))
continue;
kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY);
}
}
kfree(devices_arr);
return err;
@ -1565,10 +1568,29 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
}
args->n_success = i+1;
}
kfree(devices_arr);
mutex_unlock(&p->mutex);
if (dev->device_info->asic_family == CHIP_ALDEBARAN) {
err = amdgpu_amdkfd_gpuvm_sync_memory(dev->kgd,
(struct kgd_mem *) mem, true);
if (err) {
pr_debug("Sync memory failed, wait interrupted by user signal\n");
goto sync_memory_failed;
}
/* Flush TLBs after waiting for the page table updates to complete */
for (i = 0; i < args->n_devices; i++) {
peer = kfd_device_by_id(devices_arr[i]);
if (WARN_ON_ONCE(!peer))
continue;
peer_pdd = kfd_get_process_device_data(peer, p);
if (WARN_ON_ONCE(!peer_pdd))
continue;
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
}
}
kfree(devices_arr);
return 0;
bind_process_to_device_failed:
@ -1576,6 +1598,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
unmap_memory_from_gpu_failed:
mutex_unlock(&p->mutex);
copy_from_user_failed:
sync_memory_failed:
kfree(devices_arr);
return err;
}

View File

@ -91,6 +91,7 @@ static const struct kfd2kgd_calls *kfd2kgd_funcs[] = {
static const struct kfd_device_info kaveri_device_info = {
.asic_family = CHIP_KAVERI,
.asic_name = "kaveri",
.gfx_target_version = 70000,
.max_pasid_bits = 16,
/* max num of queues for KV.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@ -110,6 +111,7 @@ static const struct kfd_device_info kaveri_device_info = {
static const struct kfd_device_info carrizo_device_info = {
.asic_family = CHIP_CARRIZO,
.asic_name = "carrizo",
.gfx_target_version = 80001,
.max_pasid_bits = 16,
/* max num of queues for CZ.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@ -130,6 +132,7 @@ static const struct kfd_device_info carrizo_device_info = {
static const struct kfd_device_info raven_device_info = {
.asic_family = CHIP_RAVEN,
.asic_name = "raven",
.gfx_target_version = 90002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -148,6 +151,7 @@ static const struct kfd_device_info raven_device_info = {
static const struct kfd_device_info hawaii_device_info = {
.asic_family = CHIP_HAWAII,
.asic_name = "hawaii",
.gfx_target_version = 70001,
.max_pasid_bits = 16,
/* max num of queues for KV.TODO should be a dynamic value */
.max_no_of_hqd = 24,
@ -167,6 +171,7 @@ static const struct kfd_device_info hawaii_device_info = {
static const struct kfd_device_info tonga_device_info = {
.asic_family = CHIP_TONGA,
.asic_name = "tonga",
.gfx_target_version = 80002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -185,6 +190,7 @@ static const struct kfd_device_info tonga_device_info = {
static const struct kfd_device_info fiji_device_info = {
.asic_family = CHIP_FIJI,
.asic_name = "fiji",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -203,6 +209,7 @@ static const struct kfd_device_info fiji_device_info = {
static const struct kfd_device_info fiji_vf_device_info = {
.asic_family = CHIP_FIJI,
.asic_name = "fiji",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -222,6 +229,7 @@ static const struct kfd_device_info fiji_vf_device_info = {
static const struct kfd_device_info polaris10_device_info = {
.asic_family = CHIP_POLARIS10,
.asic_name = "polaris10",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -240,6 +248,7 @@ static const struct kfd_device_info polaris10_device_info = {
static const struct kfd_device_info polaris10_vf_device_info = {
.asic_family = CHIP_POLARIS10,
.asic_name = "polaris10",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -258,6 +267,7 @@ static const struct kfd_device_info polaris10_vf_device_info = {
static const struct kfd_device_info polaris11_device_info = {
.asic_family = CHIP_POLARIS11,
.asic_name = "polaris11",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -276,6 +286,7 @@ static const struct kfd_device_info polaris11_device_info = {
static const struct kfd_device_info polaris12_device_info = {
.asic_family = CHIP_POLARIS12,
.asic_name = "polaris12",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -294,6 +305,7 @@ static const struct kfd_device_info polaris12_device_info = {
static const struct kfd_device_info vegam_device_info = {
.asic_family = CHIP_VEGAM,
.asic_name = "vegam",
.gfx_target_version = 80003,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 4,
@ -312,6 +324,7 @@ static const struct kfd_device_info vegam_device_info = {
static const struct kfd_device_info vega10_device_info = {
.asic_family = CHIP_VEGA10,
.asic_name = "vega10",
.gfx_target_version = 90000,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -330,6 +343,7 @@ static const struct kfd_device_info vega10_device_info = {
static const struct kfd_device_info vega10_vf_device_info = {
.asic_family = CHIP_VEGA10,
.asic_name = "vega10",
.gfx_target_version = 90000,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -348,6 +362,7 @@ static const struct kfd_device_info vega10_vf_device_info = {
static const struct kfd_device_info vega12_device_info = {
.asic_family = CHIP_VEGA12,
.asic_name = "vega12",
.gfx_target_version = 90004,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -366,6 +381,7 @@ static const struct kfd_device_info vega12_device_info = {
static const struct kfd_device_info vega20_device_info = {
.asic_family = CHIP_VEGA20,
.asic_name = "vega20",
.gfx_target_version = 90006,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -384,6 +400,7 @@ static const struct kfd_device_info vega20_device_info = {
static const struct kfd_device_info arcturus_device_info = {
.asic_family = CHIP_ARCTURUS,
.asic_name = "arcturus",
.gfx_target_version = 90008,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -402,6 +419,7 @@ static const struct kfd_device_info arcturus_device_info = {
static const struct kfd_device_info aldebaran_device_info = {
.asic_family = CHIP_ALDEBARAN,
.asic_name = "aldebaran",
.gfx_target_version = 90010,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -420,6 +438,7 @@ static const struct kfd_device_info aldebaran_device_info = {
static const struct kfd_device_info renoir_device_info = {
.asic_family = CHIP_RENOIR,
.asic_name = "renoir",
.gfx_target_version = 90002,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -438,6 +457,7 @@ static const struct kfd_device_info renoir_device_info = {
static const struct kfd_device_info navi10_device_info = {
.asic_family = CHIP_NAVI10,
.asic_name = "navi10",
.gfx_target_version = 100100,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -456,6 +476,7 @@ static const struct kfd_device_info navi10_device_info = {
static const struct kfd_device_info navi12_device_info = {
.asic_family = CHIP_NAVI12,
.asic_name = "navi12",
.gfx_target_version = 100101,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -474,6 +495,7 @@ static const struct kfd_device_info navi12_device_info = {
static const struct kfd_device_info navi14_device_info = {
.asic_family = CHIP_NAVI14,
.asic_name = "navi14",
.gfx_target_version = 100102,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -492,6 +514,7 @@ static const struct kfd_device_info navi14_device_info = {
static const struct kfd_device_info sienna_cichlid_device_info = {
.asic_family = CHIP_SIENNA_CICHLID,
.asic_name = "sienna_cichlid",
.gfx_target_version = 100300,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -510,6 +533,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = {
static const struct kfd_device_info navy_flounder_device_info = {
.asic_family = CHIP_NAVY_FLOUNDER,
.asic_name = "navy_flounder",
.gfx_target_version = 100301,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -528,6 +552,7 @@ static const struct kfd_device_info navy_flounder_device_info = {
static const struct kfd_device_info vangogh_device_info = {
.asic_family = CHIP_VANGOGH,
.asic_name = "vangogh",
.gfx_target_version = 100303,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -546,6 +571,7 @@ static const struct kfd_device_info vangogh_device_info = {
static const struct kfd_device_info dimgrey_cavefish_device_info = {
.asic_family = CHIP_DIMGREY_CAVEFISH,
.asic_name = "dimgrey_cavefish",
.gfx_target_version = 100302,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -564,6 +590,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = {
static const struct kfd_device_info beige_goby_device_info = {
.asic_family = CHIP_BEIGE_GOBY,
.asic_name = "beige_goby",
.gfx_target_version = 100304,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -582,6 +609,7 @@ static const struct kfd_device_info beige_goby_device_info = {
static const struct kfd_device_info yellow_carp_device_info = {
.asic_family = CHIP_YELLOW_CARP,
.asic_name = "yellow_carp",
.gfx_target_version = 100305,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,
@ -600,6 +628,7 @@ static const struct kfd_device_info yellow_carp_device_info = {
static const struct kfd_device_info cyan_skillfish_device_info = {
.asic_family = CHIP_CYAN_SKILLFISH,
.asic_name = "cyan_skillfish",
.gfx_target_version = 100103,
.max_pasid_bits = 16,
.max_no_of_hqd = 24,
.doorbell_size = 8,

View File

@ -196,6 +196,7 @@ struct kfd_event_interrupt_class {
struct kfd_device_info {
enum amd_asic_type asic_family;
const char *asic_name;
uint32_t gfx_target_version;
const struct kfd_event_interrupt_class *event_interrupt_class;
unsigned int max_pasid_bits;
unsigned int max_no_of_hqd;

View File

@ -714,7 +714,8 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
if (err)
goto err_alloc_mem;
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem, pdd->drm_priv);
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem,
pdd->drm_priv, NULL);
if (err)
goto err_map_mem;

View File

@ -3019,7 +3019,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
struct svm_range *prange;
uint32_t prefetch_loc = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
uint32_t location = KFD_IOCTL_SVM_LOCATION_UNDEFINED;
uint32_t flags = 0xffffffff;
uint32_t flags_and = 0xffffffff;
uint32_t flags_or = 0;
int gpuidx;
uint32_t i;
@ -3046,12 +3047,12 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
get_accessible = true;
break;
case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
get_flags = true;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
get_granularity = true;
break;
case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
case KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE:
case KFD_IOCTL_SVM_ATTR_NO_ACCESS:
fallthrough;
@ -3069,7 +3070,8 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
if (!node) {
pr_debug("range attrs not found return default values\n");
svm_range_set_default_attributes(&location, &prefetch_loc,
&granularity, &flags);
&granularity, &flags_and);
flags_or = flags_and;
if (p->xnack_enabled)
bitmap_copy(bitmap_access, svms->bitmap_supported,
MAX_GPU_INSTANCE);
@ -3115,8 +3117,10 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
bitmap_and(bitmap_aip, bitmap_aip,
prange->bitmap_aip, MAX_GPU_INSTANCE);
}
if (get_flags)
flags &= prange->flags;
if (get_flags) {
flags_and &= prange->flags;
flags_or |= prange->flags;
}
if (get_granularity && prange->granularity < granularity)
granularity = prange->granularity;
@ -3150,7 +3154,10 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
attrs[i].type = KFD_IOCTL_SVM_ATTR_NO_ACCESS;
break;
case KFD_IOCTL_SVM_ATTR_SET_FLAGS:
attrs[i].value = flags;
attrs[i].value = flags_and;
break;
case KFD_IOCTL_SVM_ATTR_CLR_FLAGS:
attrs[i].value = ~flags_or;
break;
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
attrs[i].value = (uint32_t)granularity;

View File

@ -478,6 +478,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
dev->node_props.simd_per_cu);
sysfs_show_32bit_prop(buffer, offs, "max_slots_scratch_cu",
dev->node_props.max_slots_scratch_cu);
sysfs_show_32bit_prop(buffer, offs, "gfx_target_version",
dev->node_props.gfx_target_version);
sysfs_show_32bit_prop(buffer, offs, "vendor_id",
dev->node_props.vendor_id);
sysfs_show_32bit_prop(buffer, offs, "device_id",
@ -1360,6 +1362,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
dev->node_props.simd_arrays_per_engine =
cu_info.num_shader_arrays_per_engine;
dev->node_props.gfx_target_version = gpu->device_info->gfx_target_version;
dev->node_props.vendor_id = gpu->pdev->vendor;
dev->node_props.device_id = gpu->pdev->device;
dev->node_props.capability |=

View File

@ -78,6 +78,7 @@ struct kfd_node_properties {
uint32_t simd_per_cu;
uint32_t max_slots_scratch_cu;
uint32_t engine_id;
uint32_t gfx_target_version;
uint32_t vendor_id;
uint32_t device_id;
uint32_t location_id;

View File

@ -27,6 +27,10 @@
AMDGPUDM = amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o amdgpu_dm_color.o
ifdef CONFIG_DRM_AMD_DC_DCN
AMDGPUDM += dc_fpu.o
endif
ifneq ($(CONFIG_DRM_AMD_DC),)
AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o
endif

View File

@ -1066,19 +1066,15 @@ static void event_mall_stutter(struct work_struct *work)
static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc)
{
int max_caps = dc->caps.max_links;
struct vblank_workqueue *vblank_work;
int i = 0;
vblank_work = kcalloc(max_caps, sizeof(*vblank_work), GFP_KERNEL);
vblank_work = kzalloc(sizeof(*vblank_work), GFP_KERNEL);
if (ZERO_OR_NULL_PTR(vblank_work)) {
kfree(vblank_work);
return NULL;
}
for (i = 0; i < max_caps; i++)
INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter);
INIT_WORK(&vblank_work->mall_work, event_mall_stutter);
return vblank_work;
}
@ -1548,6 +1544,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
}
hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id =
@ -1561,7 +1558,6 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
adev->dm.dmcub_fw_version);
}
adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
adev->dm.dmub_srv = kzalloc(sizeof(*adev->dm.dmub_srv), GFP_KERNEL);
dmub_srv = adev->dm.dmub_srv;
@ -9620,7 +9616,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
} else if (amdgpu_freesync_vid_mode && aconnector &&
is_freesync_video_mode(&new_crtc_state->mode,
aconnector)) {
set_freesync_fixed_config(dm_new_crtc_state);
struct drm_display_mode *high_mode;
high_mode = get_highest_refresh_rate_mode(aconnector, false);
if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
set_freesync_fixed_config(dm_new_crtc_state);
}
}
ret = dm_atomic_get_state(state, &dm_state);

View File

@ -637,6 +637,30 @@ TRACE_EVENT(amdgpu_refresh_rate_track,
__entry->refresh_rate_ns)
);
TRACE_EVENT(dcn_fpu,
TP_PROTO(bool begin, const char *function, const int line, const int recursion_depth),
TP_ARGS(begin, function, line, recursion_depth),
TP_STRUCT__entry(
__field(bool, begin)
__field(const char *, function)
__field(int, line)
__field(int, recursion_depth)
),
TP_fast_assign(
__entry->begin = begin;
__entry->function = function;
__entry->line = line;
__entry->recursion_depth = recursion_depth;
),
TP_printk("%s: recursion_depth: %d: %s()+%d:",
__entry->begin ? "begin" : "end",
__entry->recursion_depth,
__entry->function,
__entry->line
)
);
#endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH

View File

@ -0,0 +1,144 @@
// SPDX-License-Identifier: MIT
/*
* Copyright 2021 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: AMD
*
*/
#include "dc_trace.h"
#if defined(CONFIG_X86)
#include <asm/fpu/api.h>
#elif defined(CONFIG_PPC64)
#include <asm/switch_to.h>
#include <asm/cputable.h>
#endif
/**
* DOC: DC FPU manipulation overview
*
* DC core uses FPU operations in multiple parts of the code, which requires a
* more specialized way to manage these areas' entrance. To fulfill this
* requirement, we created some wrapper functions that encapsulate
* kernel_fpu_begin/end to better fit our need in the display component. In
* summary, in this file, you can find functions related to FPU operation
* management.
*/
static DEFINE_PER_CPU(int, fpu_recursion_depth);
/**
* dc_assert_fp_enabled - Check if FPU protection is enabled
*
* This function tells if the code is already under FPU protection or not. A
* function that works as an API for a set of FPU operations can use this
* function for checking if the caller invoked it after DC_FP_START(). For
* example, take a look at dcn2x.c file.
*/
inline void dc_assert_fp_enabled(void)
{
int *pcpu, depth = 0;
pcpu = get_cpu_ptr(&fpu_recursion_depth);
depth = *pcpu;
put_cpu_ptr(&fpu_recursion_depth);
ASSERT(depth > 1);
}
/**
* dc_fpu_begin - Enables FPU protection
* @function_name: A string containing the function name for debug purposes
* (usually __func__)
*
* @line: A line number where DC_FP_START was invoked for debug purpose
* (usually __LINE__)
*
* This function is responsible for managing the use of kernel_fpu_begin() with
* the advantage of providing an event trace for debugging.
*
* Note: Do not call this function directly; always use DC_FP_START().
*/
void dc_fpu_begin(const char *function_name, const int line)
{
int *pcpu;
pcpu = get_cpu_ptr(&fpu_recursion_depth);
*pcpu += 1;
if (*pcpu == 1) {
#if defined(CONFIG_X86)
kernel_fpu_begin();
#elif defined(CONFIG_PPC64)
if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
preempt_disable();
enable_kernel_vsx();
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
preempt_disable();
enable_kernel_altivec();
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
preempt_disable();
enable_kernel_fp();
}
#endif
}
TRACE_DCN_FPU(true, function_name, line, *pcpu);
put_cpu_ptr(&fpu_recursion_depth);
}
/**
* dc_fpu_end - Disable FPU protection
* @function_name: A string containing the function name for debug purposes
* @line: A-line number where DC_FP_END was invoked for debug purpose
*
* This function is responsible for managing the use of kernel_fpu_end() with
* the advantage of providing an event trace for debugging.
*
* Note: Do not call this function directly; always use DC_FP_END().
*/
void dc_fpu_end(const char *function_name, const int line)
{
int *pcpu;
pcpu = get_cpu_ptr(&fpu_recursion_depth);
*pcpu -= 1;
if (*pcpu <= 0) {
#if defined(CONFIG_X86)
kernel_fpu_end();
#elif defined(CONFIG_PPC64)
if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
disable_kernel_vsx();
preempt_enable();
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
disable_kernel_altivec();
preempt_enable();
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
disable_kernel_fp();
preempt_enable();
}
#endif
}
TRACE_DCN_FPU(false, function_name, line, *pcpu);
put_cpu_ptr(&fpu_recursion_depth);
}

View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright 2021 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: AMD
*
*/
#ifndef __DC_FPU_H__
#define __DC_FPU_H__
void dc_assert_fp_enabled(void);
void dc_fpu_begin(const char *function_name, const int line);
void dc_fpu_end(const char *function_name, const int line);
#endif /* __DC_FPU_H__ */

View File

@ -66,9 +66,11 @@ int rn_get_active_display_cnt_wa(
for (i = 0; i < context->stream_count; i++) {
const struct dc_stream_state *stream = context->streams[i];
/* Extend the WA to DP for Linux*/
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
tmds_present = true;
}

View File

@ -3595,29 +3595,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
bool dp_retrieve_lttpr_cap(struct dc_link *link)
{
uint8_t lttpr_dpcd_data[6];
bool vbios_lttpr_enable = false;
bool vbios_lttpr_interop = false;
struct dc_bios *bios = link->dc->ctx->dc_bios;
bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
enum dc_status status = DC_ERROR_UNEXPECTED;
bool is_lttpr_present = false;
memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
/* Query BIOS to determine if LTTPR functionality is forced on by system */
if (bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
uint8_t is_vbios_lttpr_enable = 0;
bp_query_result = bios->funcs->get_lttpr_caps(bios, &is_vbios_lttpr_enable);
vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
}
if (bios->funcs->get_lttpr_interop) {
enum bp_result bp_query_result;
uint8_t is_vbios_interop_enabled = 0;
bp_query_result = bios->funcs->get_lttpr_interop(bios, &is_vbios_interop_enabled);
vbios_lttpr_interop = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled;
}
/*
* Logic to determine LTTPR mode

View File

@ -305,7 +305,7 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc(
const struct dc_state *state)
{
struct link_encoder *link_enc = NULL;
enum engine_id eng_id = ENGINE_ID_UNKNOWN;
enum engine_id eng_id;
eng_id = find_first_avail_link_enc(dc->ctx, state);
if (eng_id != ENGINE_ID_UNKNOWN)

View File

@ -1030,7 +1030,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* Timing borders are part of vactive that we are also supposed to skip in addition
* to any stream dst offset. Since dm logic assumes dst is in addressable
* space we need to add the the left and top borders to dst offsets temporarily.
* space we need to add the left and top borders to dst offsets temporarily.
* TODO: fix in DM, stream dst is supposed to be in vactive
*/
pipe_ctx->stream->dst.x += timing->h_border_left;
@ -1051,6 +1051,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
/* depends on scaling ratios and recout, does not calculate offset yet */
calculate_viewport_size(pipe_ctx);
/* Stopgap for validation of ODM + MPO on one side of screen case */
if (pipe_ctx->plane_res.scl_data.viewport.height < 1 ||
pipe_ctx->plane_res.scl_data.viewport.width < 1)
return false;
/*
* LB calculations depend on vp size, h/v_active and scaling ratios
* Setting line buffer pixel depth to 24bpp yields banding

View File

@ -45,7 +45,7 @@
/* forward declaration */
struct aux_payload;
#define DC_VER "3.2.146"
#define DC_VER "3.2.147"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@ -183,6 +183,8 @@ struct dc_caps {
unsigned int cursor_cache_size;
struct dc_plane_cap planes[MAX_PLANES];
struct dc_color_caps color;
bool vbios_lttpr_aware;
bool vbios_lttpr_enable;
};
struct dc_bug_wa {

View File

@ -37,3 +37,6 @@
#define TRACE_DCN_CLOCK_STATE(dcn_clocks) \
trace_amdgpu_dm_dc_clocks_state(dcn_clocks)
#define TRACE_DCN_FPU(begin, function, line, ref_count) \
trace_dcn_fpu(begin, function, line, ref_count)

View File

@ -464,7 +464,7 @@ void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
MASTER_UPDATE_LOCK_DB_X,
h_blank_start - 200 - 1,
(h_blank_start - 200 - 1) / optc1->opp_count,
MASTER_UPDATE_LOCK_DB_Y,
v_blank_start - 1);
}

View File

@ -35,6 +35,8 @@
#include "include/irq_service_interface.h"
#include "dcn20/dcn20_resource.h"
#include "dml/dcn2x/dcn2x.h"
#include "dcn10/dcn10_hubp.h"
#include "dcn10/dcn10_ipp.h"
#include "dcn20_hubbub.h"
@ -1974,43 +1976,6 @@ void dcn20_split_stream_for_mpc(
ASSERT(primary_pipe->plane_state);
}
void dcn20_populate_dml_writeback_from_context(
struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes)
{
int pipe_cnt, i;
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
if (!res_ctx->pipe_ctx[i].stream)
continue;
/* Set writeback information */
pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
pipes[pipe_cnt].dout.num_active_wb++;
pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
else
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
} else
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
pipe_cnt++;
}
}
int dcn20_populate_dml_pipes_from_context(
struct dc *dc,
struct dc_state *context,
@ -2392,7 +2357,9 @@ int dcn20_populate_dml_pipes_from_context(
}
/* populate writeback information */
DC_FP_START();
dc->res_pool->funcs->populate_dml_writeback_from_context(dc, res_ctx, pipes);
DC_FP_END();
return pipe_cnt;
}

View File

@ -58,8 +58,6 @@ struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
struct dc_state *state,
const struct resource_pool *pool,
struct dc_stream_state *stream);
void dcn20_populate_dml_writeback_from_context(
struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes);
struct stream_encoder *dcn20_stream_encoder_create(
enum engine_id eng_id,

View File

@ -35,6 +35,8 @@
#include "include/irq_service_interface.h"
#include "dcn20/dcn20_resource.h"
#include "dml/dcn2x/dcn2x.h"
#include "clk_mgr.h"
#include "dcn10/dcn10_hubp.h"
#include "dcn10/dcn10_ipp.h"

View File

@ -2617,6 +2617,26 @@ static bool dcn30_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
/* read VBIOS LTTPR caps */
{
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
uint8_t is_vbios_lttpr_enable = 0;
bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
}
if (ctx->dc_bios->funcs->get_lttpr_interop) {
enum bp_result bp_query_result;
uint8_t is_vbios_interop_enabled = 0;
bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios,
&is_vbios_interop_enabled);
dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled;
}
}
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {

View File

@ -146,8 +146,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc = {
.min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */
.num_states = 1,
.sr_exit_time_us = 26.5,
.sr_enter_plus_exit_time_us = 31,
.sr_exit_time_us = 35.5,
.sr_enter_plus_exit_time_us = 40,
.urgent_latency_us = 4.0,
.urgent_latency_pixel_data_only_us = 4.0,
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,

View File

@ -1968,6 +1968,22 @@ static bool dcn31_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
/* read VBIOS LTTPR caps */
{
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
uint8_t is_vbios_lttpr_enable = 0;
bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
}
/* interop bit is implicit */
{
dc->caps.vbios_lttpr_aware = true;
}
}
if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
dc->debug = debug_defaults_drv;
else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {

View File

@ -58,6 +58,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
ifdef CONFIG_DRM_AMD_DC_DCN
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
@ -70,6 +72,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(fram
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags)
@ -91,6 +94,7 @@ DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \
ifdef CONFIG_DRM_AMD_DC_DCN
DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o
DML += dcn2x/dcn2x.o
DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o

View File

@ -488,7 +488,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
// a meta element covers one 256b block of the the data surface.
// a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;

View File

@ -488,7 +488,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
// a meta element covers one 256b block of the the data surface.
// a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;

View File

@ -482,7 +482,7 @@ static void get_meta_and_pte_attr(
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
// a meta element covers one 256b block of the the data surface.
// a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;

View File

@ -0,0 +1,102 @@
// SPDX-License-Identifier: MIT
/*
* Copyright 2021 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: AMD
*
*/
#include "resource.h"
#include "dcn2x.h"
/**
* DOC: DCN2x FPU manipulation Overview
*
* The DCN architecture relies on FPU operations, which require special
* compilation flags and the use of kernel_fpu_begin/end functions; ideally, we
* want to avoid spreading FPU access across multiple files. With this idea in
* mind, this file aims to centralize all DCN20 and DCN2.1 (DCN2x) functions
* that require FPU access in a single place. Code in this file follows the
* following code pattern:
*
* 1. Functions that use FPU operations should be isolated in static functions.
* 2. The FPU functions should have the noinline attribute to ensure anything
* that deals with FP register is contained within this call.
* 3. All function that needs to be accessed outside this file requires a
* public interface that not uses any FPU reference.
* 4. Developers **must not** use DC_FP_START/END in this file, but they need
* to ensure that the caller invokes it before access any function available
* in this file. For this reason, public functions in this file must invoke
* dc_assert_fp_enabled();
*
* Let's expand a little bit more the idea in the code pattern. To fully
* isolate FPU operations in a single place, we must avoid situations where
* compilers spill FP values to registers due to FP enable in a specific C
* file. Note that even if we isolate all FPU functions in a single file and
* call its interface from other files, the compiler might enable the use of
* FPU before we call DC_FP_START. Nevertheless, it is the programmer's
* responsibility to invoke DC_FP_START/END in the correct place. To highlight
* situations where developers forgot to use the FP protection before calling
* the DC FPU interface functions, we introduce a helper that checks if the
* function is invoked under FP protection. If not, it will trigger a kernel
* warning.
*/
void dcn20_populate_dml_writeback_from_context(struct dc *dc,
struct resource_context *res_ctx,
display_e2e_pipe_params_st *pipes)
{
int pipe_cnt, i;
dc_assert_fp_enabled();
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
struct dc_writeback_info *wb_info = &res_ctx->pipe_ctx[i].stream->writeback_info[0];
if (!res_ctx->pipe_ctx[i].stream)
continue;
/* Set writeback information */
pipes[pipe_cnt].dout.wb_enable = (wb_info->wb_enabled == true) ? 1 : 0;
pipes[pipe_cnt].dout.num_active_wb++;
pipes[pipe_cnt].dout.wb.wb_src_height = wb_info->dwb_params.cnv_params.crop_height;
pipes[pipe_cnt].dout.wb.wb_src_width = wb_info->dwb_params.cnv_params.crop_width;
pipes[pipe_cnt].dout.wb.wb_dst_width = wb_info->dwb_params.dest_width;
pipes[pipe_cnt].dout.wb.wb_dst_height = wb_info->dwb_params.dest_height;
pipes[pipe_cnt].dout.wb.wb_htaps_luma = 1;
pipes[pipe_cnt].dout.wb.wb_vtaps_luma = 1;
pipes[pipe_cnt].dout.wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c;
pipes[pipe_cnt].dout.wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c;
pipes[pipe_cnt].dout.wb.wb_hratio = 1.0;
pipes[pipe_cnt].dout.wb.wb_vratio = 1.0;
if (wb_info->dwb_params.out_format == dwb_scaler_mode_yuv420) {
if (wb_info->dwb_params.output_depth == DWB_OUTPUT_PIXEL_DEPTH_8BPC)
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_8;
else
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_420_10;
} else {
pipes[pipe_cnt].dout.wb.wb_pixel_format = dm_444_32;
}
pipe_cnt++;
}
}

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright 2014 Advanced Micro Devices, Inc.
* Copyright 2021 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"),
@ -19,12 +20,15 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DCE_VIRTUAL_H__
#define __DCE_VIRTUAL_H__
#ifndef __DCN2X_H__
#define __DCN2X_H__
extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
#endif
void dcn20_populate_dml_writeback_from_context(struct dc *dc,
struct resource_context *res_ctx,
display_e2e_pipe_params_st *pipes);
#endif /* __DCN2X_H__ */

View File

@ -549,7 +549,7 @@ static void get_meta_and_pte_attr(struct display_mode_lib *mode_lib,
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
// a meta element covers one 256b block of the the data surface.
// a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
- log2_meta_req_height;

View File

@ -563,7 +563,7 @@ static void get_meta_and_pte_attr(
log2_meta_req_bytes = 6; // meta request is 64b and is 8x8byte meta element
// each 64b meta request for dcn is 8x8 meta elements and
// a meta element covers one 256b block of the the data surface.
// a meta element covers one 256b block of the data surface.
log2_meta_req_height = log2_blk256_height + 3; // meta req is 8x8 byte, each byte represent 1 blk256
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element - log2_meta_req_height;
meta_req_width = 1 << log2_meta_req_width;

View File

@ -456,7 +456,7 @@ static void dml1_rq_dlg_get_row_heights(
log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
/* each 64b meta request for dcn is 8x8 meta elements and
* a meta element covers one 256b block of the the data surface.
* a meta element covers one 256b block of the data surface.
*/
log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 */
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element
@ -718,7 +718,7 @@ static void get_surf_rq_param(
log2_meta_req_bytes = 6; /* meta request is 64b and is 8x8byte meta element */
/* each 64b meta request for dcn is 8x8 meta elements and
* a meta element covers one 256b block of the the data surface.
* a meta element covers one 256b block of the data surface.
*/
log2_meta_req_height = log2_blk256_height + 3; /* meta req is 8x8 byte, each byte represent 1 blk256 */
log2_meta_req_width = log2_meta_req_bytes + 8 - log2_bytes_per_element

View File

@ -51,38 +51,9 @@
#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_X86)
#include <asm/fpu/api.h>
#define DC_FP_START() kernel_fpu_begin()
#define DC_FP_END() kernel_fpu_end()
#elif defined(CONFIG_PPC64)
#include <asm/switch_to.h>
#include <asm/cputable.h>
#define DC_FP_START() { \
if (cpu_has_feature(CPU_FTR_VSX_COMP)) { \
preempt_disable(); \
enable_kernel_vsx(); \
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { \
preempt_disable(); \
enable_kernel_altivec(); \
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { \
preempt_disable(); \
enable_kernel_fp(); \
} \
}
#define DC_FP_END() { \
if (cpu_has_feature(CPU_FTR_VSX_COMP)) { \
disable_kernel_vsx(); \
preempt_enable(); \
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { \
disable_kernel_altivec(); \
preempt_enable(); \
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { \
disable_kernel_fp(); \
preempt_enable(); \
} \
}
#endif
#include "amdgpu_dm/dc_fpu.h"
#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
#endif
/*

View File

@ -47,10 +47,10 @@
/* Firmware versioning. */
#ifdef DMUB_EXPOSE_VERSION
#define DMUB_FW_VERSION_GIT_HASH 0xe599e0896
#define DMUB_FW_VERSION_GIT_HASH 0x6d13d5e2c
#define DMUB_FW_VERSION_MAJOR 0
#define DMUB_FW_VERSION_MINOR 0
#define DMUB_FW_VERSION_REVISION 76
#define DMUB_FW_VERSION_REVISION 77
#define DMUB_FW_VERSION_TEST 0
#define DMUB_FW_VERSION_VBIOS 0
#define DMUB_FW_VERSION_HOTFIX 0

View File

@ -270,11 +270,13 @@ void dmub_dcn31_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
bool dmub_dcn31_is_hw_init(struct dmub_srv *dmub)
{
uint32_t is_hw_init;
union dmub_fw_boot_status status;
uint32_t is_enable;
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
status.all = REG_READ(DMCUB_SCRATCH0);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enable);
return is_hw_init != 0;
return is_enable != 0 && status.bits.dal_fw;
}
bool dmub_dcn31_is_supported(struct dmub_srv *dmub)

View File

@ -508,6 +508,10 @@
#define regCP_ME2_PIPE2_INT_STATUS_BASE_IDX 0
#define regCP_ME2_PIPE3_INT_STATUS 0x1094
#define regCP_ME2_PIPE3_INT_STATUS_BASE_IDX 0
#define regCP_ME1_INT_STAT_DEBUG 0x1095
#define regCP_ME1_INT_STAT_DEBUG_BASE_IDX 0
#define regCP_ME2_INT_STAT_DEBUG 0x1096
#define regCP_ME2_INT_STAT_DEBUG_BASE_IDX 0
#define regCC_GC_EDC_CONFIG 0x1098
#define regCC_GC_EDC_CONFIG_BASE_IDX 0
#define regCP_ME1_PIPE_PRIORITY_CNTS 0x1099

View File

@ -2989,6 +2989,60 @@
#define CP_ME1_PIPE3_INT_STATUS__GENERIC2_INT_STATUS_MASK 0x20000000L
#define CP_ME1_PIPE3_INT_STATUS__GENERIC1_INT_STATUS_MASK 0x40000000L
#define CP_ME1_PIPE3_INT_STATUS__GENERIC0_INT_STATUS_MASK 0x80000000L
//CP_ME1_INT_STAT_DEBUG
#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
#define CP_ME1_INT_STAT_DEBUG__GPF_INT_ASSERTED__SHIFT 0x10
#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
#define CP_ME1_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x00001000L
#define CP_ME1_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x00002000L
#define CP_ME1_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
#define CP_ME1_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x00008000L
#define CP_ME1_INT_STAT_DEBUG__GPF_INT_ASSERTED_MASK 0x00010000L
#define CP_ME1_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
#define CP_ME1_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
#define CP_ME1_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
#define CP_ME1_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
#define CP_ME1_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
#define CP_ME1_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
#define CP_ME1_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
#define CP_ME1_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
//CP_ME2_INT_STAT_DEBUG
#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED__SHIFT 0xc
#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED__SHIFT 0xd
#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0xe
#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS__SHIFT 0xf
#define CP_ME2_INT_STAT_DEBUG__GPF_INT_ASSERTED__SHIFT 0x10
#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x11
#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x17
#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x18
#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x1a
#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x1b
#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x1d
#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x1e
#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x1f
#define CP_ME2_INT_STAT_DEBUG__CMP_QUERY_STATUS_INT_ASSERTED_MASK 0x00001000L
#define CP_ME2_INT_STAT_DEBUG__DEQUEUE_REQUEST_INT_ASSERTED_MASK 0x00002000L
#define CP_ME2_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
#define CP_ME2_INT_STAT_DEBUG__SUA_VIOLATION_INT_STATUS_MASK 0x00008000L
#define CP_ME2_INT_STAT_DEBUG__GPF_INT_ASSERTED_MASK 0x00010000L
#define CP_ME2_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
#define CP_ME2_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
#define CP_ME2_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
#define CP_ME2_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
#define CP_ME2_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
#define CP_ME2_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
#define CP_ME2_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
#define CP_ME2_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
//CP_ME2_PIPE0_INT_STATUS
#define CP_ME2_PIPE0_INT_STATUS__CMP_QUERY_STATUS_INT_STATUS__SHIFT 0xc
#define CP_ME2_PIPE0_INT_STATUS__DEQUEUE_REQUEST_INT_STATUS__SHIFT 0xd

View File

@ -590,7 +590,7 @@ struct atom_firmware_info_v3_4 {
uint8_t board_i2c_feature_id; // enum of atom_board_i2c_feature_id_def
uint8_t board_i2c_feature_gpio_id; // i2c id find in gpio_lut data table gpio_id
uint8_t board_i2c_feature_slave_addr;
uint8_t reserved3;
uint8_t ras_rom_i2c_slave_addr;
uint16_t bootup_mvddq_mv;
uint16_t bootup_mvpp_mv;
uint32_t zfbstartaddrin16mb;

View File

@ -282,6 +282,7 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(TDC), \
__SMU_DUMMY_MAP(THERMAL), \
__SMU_DUMMY_MAP(GFX_PER_CU_CG), \
__SMU_DUMMY_MAP(DATA_CALCULATIONS), \
__SMU_DUMMY_MAP(RM), \
__SMU_DUMMY_MAP(DS_DCEFCLK), \
__SMU_DUMMY_MAP(ACDC), \

View File

@ -26,7 +26,7 @@
#include "amdgpu_smu.h"
#define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x03
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
#define SMU13_DRIVER_IF_VERSION_ALDE 0x07
/* MP Apertures */

View File

@ -111,7 +111,9 @@ typedef struct {
uint32_t InWhisperMode : 1;
uint32_t spare0 : 1;
uint32_t ZstateStatus : 4;
uint32_t spare1 :12;
uint32_t spare1 : 4;
uint32_t DstateFun : 4;
uint32_t DstateDev : 4;
// MP1_EXT_SCRATCH2
uint32_t P2JobHandler :24;
uint32_t RsmuPmiP2FinishedCnt : 8;

View File

@ -1580,7 +1580,7 @@ static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr,
}
if (smu10_data->gfx_actual_soft_min_freq > smu10_data->gfx_actual_soft_max_freq) {
pr_err("The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
pr_err("The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
smu10_data->gfx_actual_soft_min_freq, smu10_data->gfx_actual_soft_max_freq);
return -EINVAL;
}

View File

@ -353,8 +353,7 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
uint32_t val;
if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO ||
powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) {
if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO) {
val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
smu_baco->platform_support =
(val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :

View File

@ -256,7 +256,7 @@ static int vangogh_tables_init(struct smu_context *smu)
return 0;
err3_out:
kfree(smu_table->clocks_table);
kfree(smu_table->watermarks_table);
err2_out:
kfree(smu_table->gpu_metrics_table);
err1_out:

View File

@ -150,7 +150,7 @@ static const struct cmn2asic_mapping aldebaran_clk_map[SMU_CLK_COUNT] = {
};
static const struct cmn2asic_mapping aldebaran_feature_mask_map[SMU_FEATURE_COUNT] = {
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_PREFETCHER_BIT, FEATURE_DATA_CALCULATIONS),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DATA_CALCULATIONS_BIT, FEATURE_DATA_CALCULATIONS),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_GFXCLK_BIT, FEATURE_DPM_GFXCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_UCLK_BIT, FEATURE_DPM_UCLK_BIT),
ALDEBARAN_FEA_MAP(SMU_FEATURE_DPM_SOCCLK_BIT, FEATURE_DPM_SOCCLK_BIT),

View File

@ -2802,8 +2802,8 @@ ucMaxNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of t
ucMinNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
*/

View File

@ -28,6 +28,7 @@
#include <drm/drm_vblank.h>
#include <drm/radeon_drm.h>
#include <drm/drm_fourcc.h>
#include "atom.h"
#include "avivod.h"
@ -1414,10 +1415,15 @@ void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base,
bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
/* update the scanout addresses */
/* flip at hsync for async, default is vsync */
WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
/* update pitch */
WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset,
fb->pitches[0] / fb->format->cpp[0]);
/* update the scanout addresses */
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,

View File

@ -162,6 +162,8 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
uint32_t crtc_pitch, pitch_pixels;
struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
int i;
@ -169,6 +171,13 @@ void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool
/* update the scanout addresses */
WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
/* update pitch */
pitch_pixels = fb->pitches[0] / fb->format->cpp[0];
crtc_pitch = DIV_ROUND_UP(pitch_pixels * fb->format->cpp[0] * 8,
fb->format->cpp[0] * 8 * 8);
crtc_pitch |= crtc_pitch << 16;
WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
/* Wait for update_pending to go high. */
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)

View File

@ -353,7 +353,7 @@
# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
# define R300_PVS_CNTL_1_POS_END_SHIFT 10
# define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20
/* Addresses are relative the the vertex program parameters area. */
/* Addresses are relative the vertex program parameters area. */
#define R300_VAP_PVS_CNTL_2 0x22D4
# define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
# define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16

View File

@ -406,7 +406,7 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell)
/*
* radeon_wb_*()
* Writeback is the the method by which the the GPU updates special pages
* Writeback is the method by which the GPU updates special pages
* in memory with the status of certain GPU events (fences, ring pointers,
* etc.).
*/

View File

@ -54,6 +54,7 @@ radeonfb_open(struct fb_info *info, int user)
struct radeon_fbdev *rfbdev = info->par;
struct radeon_device *rdev = rfbdev->rdev;
int ret = pm_runtime_get_sync(rdev->ddev->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_mark_last_busy(rdev->ddev->dev);
pm_runtime_put_autosuspend(rdev->ddev->dev);
@ -196,9 +197,8 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
radeon_bo_check_tiling(rbo, 0, 0);
ret = radeon_bo_kmap(rbo, NULL);
radeon_bo_unreserve(rbo);
if (ret) {
if (ret)
goto out_unref;
}
*gobj_p = gobj;
return 0;
@ -294,9 +294,6 @@ static int radeonfb_create(struct drm_fb_helper *helper,
return 0;
out:
if (rbo) {
}
if (fb && ret) {
drm_gem_object_put(gobj);
drm_framebuffer_unregister_private(fb);

View File

@ -50,7 +50,7 @@
* for GPU/CPU synchronization. When the fence is written,
* it is expected that all buffers associated with that fence
* are no longer in use by the associated ring on the GPU and
* that the the relevant GPU caches have been flushed. Whether
* that the relevant GPU caches have been flushed. Whether
* we use a scratch register or memory location depends on the asic
* and whether writeback is enabled.
*/

View File

@ -41,7 +41,7 @@
* (uncached system pages).
* Each VM has an ID associated with it and there is a page table
* associated with each VMID. When execting a command buffer,
* the kernel tells the the ring what VMID to use for that command
* the kernel tells the ring what VMID to use for that command
* buffer. VMIDs are allocated dynamically as commands are submitted.
* The userspace drivers maintain their own address space and the kernel
* sets up their pages tables accordingly when they submit their

View File

@ -41,6 +41,7 @@
#include <drm/drm_device.h>
#include <drm/drm_vblank.h>
#include <drm/drm_fourcc.h>
#include "atom.h"
#include "radeon.h"
@ -118,6 +119,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
int i;
@ -125,9 +127,13 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, boo
tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */
/* flip at hsync for async, default is vsync */
WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
/* update pitch */
WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset,
fb->pitches[0] / fb->format->cpp[0]);
/* update the scanout addresses */
WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base);
WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,

View File

@ -32,6 +32,7 @@
#include <drm/drm_device.h>
#include <drm/radeon_drm.h>
#include <drm/drm_fourcc.h>
#include "atom.h"
#include "avivod.h"
@ -809,6 +810,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev)
void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
int i;
@ -816,9 +818,13 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, boo
tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */
/* flip at hsync for async, default is vsync */
WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
/* update pitch */
WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset,
fb->pitches[0] / fb->format->cpp[0]);
/* update the scanout addresses */
if (radeon_crtc->crtc_id) {
WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));

View File

@ -31,9 +31,10 @@
* - 1.3 - Add SMI events support
* - 1.4 - Indicate new SRAM EDC bit in device properties
* - 1.5 - Add SVM API
* - 1.6 - Query clear flags in SVM get_attr API
*/
#define KFD_IOCTL_MAJOR_VERSION 1
#define KFD_IOCTL_MINOR_VERSION 5
#define KFD_IOCTL_MINOR_VERSION 6
struct kfd_ioctl_get_version_args {
__u32 major_version; /* from KFD */
@ -575,18 +576,19 @@ struct kfd_ioctl_svm_attribute {
* @KFD_IOCTL_SVM_ATTR_PREFERRED_LOC or
* @KFD_IOCTL_SVM_ATTR_PREFETCH_LOC resepctively. For
* @KFD_IOCTL_SVM_ATTR_SET_FLAGS, flags of all pages will be
* aggregated by bitwise AND. The minimum migration granularity
* throughout the range will be returned for
* @KFD_IOCTL_SVM_ATTR_GRANULARITY.
* aggregated by bitwise AND. That means, a flag will be set in the
* output, if that flag is set for all pages in the range. For
* @KFD_IOCTL_SVM_ATTR_CLR_FLAGS, flags of all pages will be
* aggregated by bitwise NOR. That means, a flag will be set in the
* output, if that flag is clear for all pages in the range.
* The minimum migration granularity throughout the range will be
* returned for @KFD_IOCTL_SVM_ATTR_GRANULARITY.
*
* Querying of accessibility attributes works by initializing the
* attribute type to @KFD_IOCTL_SVM_ATTR_ACCESS and the value to the
* GPUID being queried. Multiple attributes can be given to allow
* querying multiple GPUIDs. The ioctl function overwrites the
* attribute type to indicate the access for the specified GPU.
*
* @KFD_IOCTL_SVM_ATTR_CLR_FLAGS is invalid for
* @KFD_IOCTL_SVM_OP_GET_ATTR.
*/
struct kfd_ioctl_svm_args {
__u64 start_addr;