mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
Merge tag 'amd-drm-next-5.16-2021-10-29' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.16-2021-10-29: amdgpu: - RAS fixes - Fix a potential memory leak in device tear down - Add a stutter mode quirk - Misc display fixes - Further display FP refactoring - Display USB4 fixes - Display DP2.0 fixes - DCN 3.1 fixes - Display 8 ch audio fix - Fix DMA mask regression for SI parts - Aldebaran fixes amdkfd: - userptr fix - BO lifetime fix - Misc code cleanup UAPI: - Minor header cleanup (no functional change) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20211029184338.4863-1-alexander.deucher@amd.com
This commit is contained in:
commit
d9bd054177
@ -205,6 +205,7 @@ extern struct amdgpu_mgpu_info mgpu_info;
|
||||
extern int amdgpu_ras_enable;
|
||||
extern uint amdgpu_ras_mask;
|
||||
extern int amdgpu_bad_page_threshold;
|
||||
extern bool amdgpu_ignore_bad_page_threshold;
|
||||
extern struct amdgpu_watchdog_timer amdgpu_watchdog_timer;
|
||||
extern int amdgpu_async_gfx_ring;
|
||||
extern int amdgpu_mcbp;
|
||||
|
@ -279,6 +279,8 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, bool intr);
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_dev *kgd,
|
||||
struct kgd_mem *mem, void **kptr, uint64_t *size);
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem);
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
|
||||
struct dma_fence **ef);
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
||||
|
@ -1871,6 +1871,16 @@ bo_reserve_failed:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_dev *kgd, struct kgd_mem *mem)
|
||||
{
|
||||
struct amdgpu_bo *bo = mem->bo;
|
||||
|
||||
amdgpu_bo_reserve(bo, true);
|
||||
amdgpu_bo_kunmap(bo);
|
||||
amdgpu_bo_unpin(bo);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd,
|
||||
struct kfd_vm_fault_info *mem)
|
||||
{
|
||||
@ -2041,19 +2051,26 @@ static int update_invalid_user_pages(struct amdkfd_process_info *process_info,
|
||||
/* Get updated user pages */
|
||||
ret = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages);
|
||||
if (ret) {
|
||||
pr_debug("%s: Failed to get user pages: %d\n",
|
||||
__func__, ret);
|
||||
pr_debug("Failed %d to get user pages\n", ret);
|
||||
|
||||
/* Return error -EBUSY or -ENOMEM, retry restore */
|
||||
return ret;
|
||||
/* Return -EFAULT bad address error as success. It will
|
||||
* fail later with a VM fault if the GPU tries to access
|
||||
* it. Better than hanging indefinitely with stalled
|
||||
* user mode queues.
|
||||
*
|
||||
* Return other error -EBUSY or -ENOMEM to retry restore
|
||||
*/
|
||||
if (ret != -EFAULT)
|
||||
return ret;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* FIXME: Cannot ignore the return code, must hold
|
||||
* notifier_lock
|
||||
*/
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Cannot ignore the return code, must hold
|
||||
* notifier_lock
|
||||
*/
|
||||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
|
||||
/* Mark the BO as valid unless it was invalidated
|
||||
* again concurrently.
|
||||
*/
|
||||
|
@ -3852,8 +3852,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
|
||||
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_device_ip_fini(adev);
|
||||
amdgpu_fence_driver_sw_fini(adev);
|
||||
amdgpu_device_ip_fini(adev);
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
adev->accel_working = false;
|
||||
|
@ -931,6 +931,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 0, 0);
|
||||
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 0, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 0, 0);
|
||||
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 0, 0);
|
||||
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 1, 0);
|
||||
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(6, 1, 0);
|
||||
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 0, 0);
|
||||
@ -951,6 +952,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 0, 1);
|
||||
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 0, 1);
|
||||
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 0, 1);
|
||||
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 0, 1);
|
||||
adev->ip_versions[DF_HWIP][0] = IP_VERSION(2, 5, 0);
|
||||
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(6, 2, 0);
|
||||
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 0);
|
||||
@ -1009,6 +1011,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 2, 0);
|
||||
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 2, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 2, 0);
|
||||
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 2, 0);
|
||||
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 0);
|
||||
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 0);
|
||||
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 1);
|
||||
@ -1018,6 +1021,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(11, 0, 2);
|
||||
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 0);
|
||||
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(7, 2, 0);
|
||||
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(7, 2, 0);
|
||||
adev->ip_versions[VCE_HWIP][0] = IP_VERSION(4, 1, 0);
|
||||
adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 1, 0);
|
||||
break;
|
||||
@ -1030,6 +1034,13 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 2, 1);
|
||||
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 2, 1);
|
||||
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][0] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][1] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][2] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][3] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][4] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][5] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[SDMA1_HWIP][6] = IP_VERSION(4, 2, 2);
|
||||
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 1);
|
||||
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 1);
|
||||
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 1, 2);
|
||||
@ -1039,6 +1050,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(11, 0, 3);
|
||||
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 1);
|
||||
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(2, 5, 0);
|
||||
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 5, 0);
|
||||
break;
|
||||
case CHIP_ALDEBARAN:
|
||||
aldebaran_reg_base_init(adev);
|
||||
@ -1049,6 +1061,10 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[OSSSYS_HWIP][0] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[HDP_HWIP][0] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][0] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][1] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][2] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][3] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[SDMA0_HWIP][4] = IP_VERSION(4, 4, 0);
|
||||
adev->ip_versions[DF_HWIP][0] = IP_VERSION(3, 6, 2);
|
||||
adev->ip_versions[NBIO_HWIP][0] = IP_VERSION(7, 4, 4);
|
||||
adev->ip_versions[UMC_HWIP][0] = IP_VERSION(6, 7, 0);
|
||||
@ -1058,6 +1074,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
||||
adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(13, 0, 2);
|
||||
adev->ip_versions[GC_HWIP][0] = IP_VERSION(9, 4, 2);
|
||||
adev->ip_versions[UVD_HWIP][0] = IP_VERSION(2, 6, 0);
|
||||
adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 6, 0);
|
||||
adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 1, 0);
|
||||
break;
|
||||
default:
|
||||
|
@ -877,7 +877,7 @@ module_param_named(reset_method, amdgpu_reset_method, int, 0444);
|
||||
* result in the GPU entering bad status when the number of total
|
||||
* faulty pages by ECC exceeds the threshold value.
|
||||
*/
|
||||
MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)");
|
||||
MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement, -2 = ignore bad page threshold)");
|
||||
module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(num_kcq, "number of kernel compute queue user want to setup (8 if set to greater than 8 or less than 0, only affect gfx 8+)");
|
||||
|
@ -340,32 +340,32 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info,
|
||||
case AMDGPU_INFO_FW_TA:
|
||||
switch (query_fw->index) {
|
||||
case TA_FW_TYPE_PSP_XGMI:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.xgmi_context.context.bin_desc.fw_version;
|
||||
fw_info->feature = adev->psp.xgmi_context.context
|
||||
.bin_desc.feature_version;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAS:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.ras_context.context.bin_desc.fw_version;
|
||||
fw_info->feature = adev->psp.ras_context.context
|
||||
.bin_desc.feature_version;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_HDCP:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.hdcp_context.context.bin_desc.fw_version;
|
||||
fw_info->feature = adev->psp.hdcp_context.context
|
||||
.bin_desc.feature_version;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_DTM:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.dtm_context.context.bin_desc.fw_version;
|
||||
fw_info->feature = adev->psp.dtm_context.context
|
||||
.bin_desc.feature_version;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAP:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.rap_context.context.bin_desc.fw_version;
|
||||
fw_info->feature = adev->psp.rap_context.context
|
||||
.bin_desc.feature_version;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_SECUREDISPLAY:
|
||||
fw_info->ver = adev->psp.ta_fw_version;
|
||||
fw_info->ver = adev->psp.securedisplay_context.context.bin_desc.fw_version;
|
||||
fw_info->feature =
|
||||
adev->psp.securedisplay_context.context.bin_desc
|
||||
.feature_version;
|
||||
|
@ -1115,7 +1115,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
|
||||
static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
|
||||
{
|
||||
return psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
|
||||
psp->xgmi_context.context.bin_desc.feature_version >= 0x2000000b;
|
||||
psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3108,32 +3108,32 @@ static int parse_ta_bin_descriptor(struct psp_context *psp,
|
||||
psp->asd_context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_XGMI:
|
||||
psp->xgmi_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->xgmi_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->xgmi_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->xgmi_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAS:
|
||||
psp->ras_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ras_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->ras_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->ras_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_HDCP:
|
||||
psp->hdcp_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->hdcp_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->hdcp_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_DTM:
|
||||
psp->dtm_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->dtm_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->dtm_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->dtm_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_RAP:
|
||||
psp->rap_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version);
|
||||
psp->rap_context.context.bin_desc.fw_version = le32_to_cpu(desc->fw_version);
|
||||
psp->rap_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes);
|
||||
psp->rap_context.context.bin_desc.start_addr = ucode_start_addr;
|
||||
break;
|
||||
case TA_FW_TYPE_PSP_SECUREDISPLAY:
|
||||
psp->securedisplay_context.context.bin_desc.feature_version =
|
||||
psp->securedisplay_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(desc->fw_version);
|
||||
psp->securedisplay_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(desc->size_bytes);
|
||||
|
@ -1077,6 +1077,13 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
if (res)
|
||||
DRM_ERROR("RAS table incorrect checksum or error:%d\n",
|
||||
res);
|
||||
|
||||
/* Warn if we are at 90% of the threshold or above
|
||||
*/
|
||||
if (10 * control->ras_num_recs >= 9 * ras->bad_page_cnt_threshold)
|
||||
dev_warn(adev->dev, "RAS records:%u exceeds 90%% of threshold:%d",
|
||||
control->ras_num_recs,
|
||||
ras->bad_page_cnt_threshold);
|
||||
} else if (hdr->header == RAS_TABLE_HDR_BAD &&
|
||||
amdgpu_bad_page_threshold != 0) {
|
||||
res = __verify_ras_table_checksum(control);
|
||||
@ -1098,11 +1105,18 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
res = amdgpu_ras_eeprom_correct_header_tag(control,
|
||||
RAS_TABLE_HDR_VAL);
|
||||
} else {
|
||||
*exceed_err_limit = true;
|
||||
dev_err(adev->dev,
|
||||
"RAS records:%d exceed threshold:%d, "
|
||||
"GPU will not be initialized. Replace this GPU or increase the threshold",
|
||||
dev_err(adev->dev, "RAS records:%d exceed threshold:%d",
|
||||
control->ras_num_recs, ras->bad_page_cnt_threshold);
|
||||
if (amdgpu_bad_page_threshold == -2) {
|
||||
dev_warn(adev->dev, "GPU will be initialized due to bad_page_threshold = -2.");
|
||||
res = 0;
|
||||
} else {
|
||||
*exceed_err_limit = true;
|
||||
dev_err(adev->dev,
|
||||
"RAS records:%d exceed threshold:%d, "
|
||||
"GPU will not be initialized. Replace this GPU or increase the threshold",
|
||||
control->ras_num_recs, ras->bad_page_cnt_threshold);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DRM_INFO("Creating a new EEPROM table");
|
||||
|
@ -696,6 +696,9 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages)
|
||||
true, NULL);
|
||||
out_unlock:
|
||||
mmap_read_unlock(mm);
|
||||
if (r)
|
||||
pr_debug("failed %d to get user pages 0x%lx\n", r, start);
|
||||
|
||||
mmput(mm);
|
||||
|
||||
return r;
|
||||
|
@ -527,8 +527,8 @@ FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version);
|
||||
FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version);
|
||||
FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version);
|
||||
FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version);
|
||||
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.feature_version);
|
||||
FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi_context.context.bin_desc.feature_version);
|
||||
FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.fw_version);
|
||||
FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi_context.context.bin_desc.fw_version);
|
||||
FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version);
|
||||
FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version);
|
||||
FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version);
|
||||
|
@ -535,9 +535,9 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev)
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD,
|
||||
adev->psp.asd_context.bin_desc.fw_version);
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS,
|
||||
adev->psp.ras_context.context.bin_desc.feature_version);
|
||||
adev->psp.ras_context.context.bin_desc.fw_version);
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI,
|
||||
adev->psp.xgmi_context.context.bin_desc.feature_version);
|
||||
adev->psp.xgmi_context.context.bin_desc.fw_version);
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version);
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version);
|
||||
POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version);
|
||||
|
@ -706,6 +706,11 @@ int gfx_v9_4_2_do_edc_gpr_workarounds(struct amdgpu_device *adev)
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
return 0;
|
||||
|
||||
/* Workaround for ALDEBARAN, skip GPRs init in GPU reset.
|
||||
Will remove it once GPRs init algorithm works for all CU settings. */
|
||||
if (amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
||||
gfx_v9_4_2_do_sgprs_init(adev);
|
||||
|
||||
gfx_v9_4_2_do_vgprs_init(adev);
|
||||
|
@ -841,12 +841,12 @@ static int gmc_v6_0_sw_init(void *handle)
|
||||
|
||||
adev->gmc.mc_mask = 0xffffffffffULL;
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
|
||||
if (r) {
|
||||
dev_warn(adev->dev, "No suitable DMA available.\n");
|
||||
return r;
|
||||
}
|
||||
adev->need_swiotlb = drm_need_swiotlb(44);
|
||||
adev->need_swiotlb = drm_need_swiotlb(40);
|
||||
|
||||
r = gmc_v6_0_init_microcode(adev);
|
||||
if (r) {
|
||||
|
@ -84,7 +84,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)
|
||||
adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@ -92,7 +92,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
@ -100,7 +100,7 @@ static int psp_v10_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
|
||||
le32_to_cpu(ta_hdr->dtm.offset_bytes);
|
||||
|
||||
adev->psp.securedisplay_context.context.bin_desc.feature_version =
|
||||
adev->psp.securedisplay_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->securedisplay.fw_version);
|
||||
adev->psp.securedisplay_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->securedisplay.size_bytes);
|
||||
|
@ -151,7 +151,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.xgmi_context.context.bin_desc.feature_version =
|
||||
adev->psp.xgmi_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->xgmi.fw_version);
|
||||
adev->psp.xgmi_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->xgmi.size_bytes);
|
||||
@ -159,7 +159,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
(uint8_t *)ta_hdr +
|
||||
le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
adev->psp.ras_context.context.bin_desc.feature_version =
|
||||
adev->psp.ras_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->ras.fw_version);
|
||||
adev->psp.ras_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->ras.size_bytes);
|
||||
@ -192,7 +192,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
goto out2;
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@ -203,7 +203,7 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
|
@ -84,7 +84,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
ta_hdr = (const struct ta_firmware_header_v1_0 *)
|
||||
adev->psp.ta_fw->data;
|
||||
adev->psp.hdcp_context.context.bin_desc.feature_version =
|
||||
adev->psp.hdcp_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->hdcp.fw_version);
|
||||
adev->psp.hdcp_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->hdcp.size_bytes);
|
||||
@ -94,7 +94,7 @@ static int psp_v12_0_init_microcode(struct psp_context *psp)
|
||||
|
||||
adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
|
||||
|
||||
adev->psp.dtm_context.context.bin_desc.feature_version =
|
||||
adev->psp.dtm_context.context.bin_desc.fw_version =
|
||||
le32_to_cpu(ta_hdr->dtm.fw_version);
|
||||
adev->psp.dtm_context.context.bin_desc.size_bytes =
|
||||
le32_to_cpu(ta_hdr->dtm.size_bytes);
|
||||
|
@ -405,7 +405,7 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
retval = pqm_update_queue(&p->pqm, args->queue_id, &properties);
|
||||
retval = pqm_update_queue_properties(&p->pqm, args->queue_id, &properties);
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
@ -418,7 +418,7 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
int retval;
|
||||
const int max_num_cus = 1024;
|
||||
struct kfd_ioctl_set_cu_mask_args *args = data;
|
||||
struct queue_properties properties;
|
||||
struct mqd_update_info minfo = {0};
|
||||
uint32_t __user *cu_mask_ptr = (uint32_t __user *)args->cu_mask_ptr;
|
||||
size_t cu_mask_size = sizeof(uint32_t) * (args->num_cu_mask / 32);
|
||||
|
||||
@ -428,8 +428,8 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
properties.cu_mask_count = args->num_cu_mask;
|
||||
if (properties.cu_mask_count == 0) {
|
||||
minfo.cu_mask.count = args->num_cu_mask;
|
||||
if (minfo.cu_mask.count == 0) {
|
||||
pr_debug("CU mask cannot be 0");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -438,32 +438,33 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
|
||||
* limit of max_num_cus bits. We can then just drop any CU mask bits
|
||||
* past max_num_cus bits and just use the first max_num_cus bits.
|
||||
*/
|
||||
if (properties.cu_mask_count > max_num_cus) {
|
||||
if (minfo.cu_mask.count > max_num_cus) {
|
||||
pr_debug("CU mask cannot be greater than 1024 bits");
|
||||
properties.cu_mask_count = max_num_cus;
|
||||
minfo.cu_mask.count = max_num_cus;
|
||||
cu_mask_size = sizeof(uint32_t) * (max_num_cus/32);
|
||||
}
|
||||
|
||||
properties.cu_mask = kzalloc(cu_mask_size, GFP_KERNEL);
|
||||
if (!properties.cu_mask)
|
||||
minfo.cu_mask.ptr = kzalloc(cu_mask_size, GFP_KERNEL);
|
||||
if (!minfo.cu_mask.ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
retval = copy_from_user(properties.cu_mask, cu_mask_ptr, cu_mask_size);
|
||||
retval = copy_from_user(minfo.cu_mask.ptr, cu_mask_ptr, cu_mask_size);
|
||||
if (retval) {
|
||||
pr_debug("Could not copy CU mask from userspace");
|
||||
kfree(properties.cu_mask);
|
||||
return -EFAULT;
|
||||
retval = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
minfo.update_flag = UPDATE_FLAG_CU_MASK;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
retval = pqm_set_cu_mask(&p->pqm, args->queue_id, &properties);
|
||||
retval = pqm_update_mqd(&p->pqm, args->queue_id, &minfo);
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
if (retval)
|
||||
kfree(properties.cu_mask);
|
||||
|
||||
out:
|
||||
kfree(minfo.cu_mask.ptr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1011,11 +1012,6 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
void *mem, *kern_addr;
|
||||
uint64_t size;
|
||||
|
||||
if (p->signal_page) {
|
||||
pr_err("Event page is already set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfd = kfd_device_by_id(GET_GPU_ID(args->event_page_offset));
|
||||
if (!kfd) {
|
||||
pr_err("Getting device by id failed in %s\n", __func__);
|
||||
@ -1023,6 +1019,13 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
}
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
if (p->signal_page) {
|
||||
pr_err("Event page is already set\n");
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
pdd = kfd_bind_process_to_device(kfd, p);
|
||||
if (IS_ERR(pdd)) {
|
||||
err = PTR_ERR(pdd);
|
||||
@ -1037,20 +1040,24 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kfd->kgd,
|
||||
mem, &kern_addr, &size);
|
||||
if (err) {
|
||||
pr_err("Failed to map event page to kernel\n");
|
||||
return err;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
err = kfd_event_page_set(p, kern_addr, size);
|
||||
if (err) {
|
||||
pr_err("Failed to set event page\n");
|
||||
return err;
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kfd->kgd, mem);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
p->signal_handle = args->event_page_offset;
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
err = kfd_event_create(filp, p, args->event_type,
|
||||
@ -1368,6 +1375,15 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
/*
|
||||
* Safeguard to prevent user space from freeing signal BO.
|
||||
* It will be freed at process termination.
|
||||
*/
|
||||
if (p->signal_handle && (p->signal_handle == args->handle)) {
|
||||
pr_err("Free signal BO is not allowed\n");
|
||||
ret = -EPERM;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
pdd = kfd_get_process_device_data(dev, p);
|
||||
if (!pdd) {
|
||||
|
@ -557,7 +557,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int update_queue(struct device_queue_manager *dqm, struct queue *q)
|
||||
static int update_queue(struct device_queue_manager *dqm, struct queue *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
int retval = 0;
|
||||
struct mqd_manager *mqd_mgr;
|
||||
@ -605,7 +606,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
|
||||
}
|
||||
}
|
||||
|
||||
mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties);
|
||||
mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties, minfo);
|
||||
|
||||
/*
|
||||
* check active state vs. the previous state and modify
|
||||
|
@ -93,7 +93,7 @@ struct device_queue_manager_ops {
|
||||
struct queue *q);
|
||||
|
||||
int (*update_queue)(struct device_queue_manager *dqm,
|
||||
struct queue *q);
|
||||
struct queue *q, struct mqd_update_info *minfo);
|
||||
|
||||
int (*register_process)(struct device_queue_manager *dqm,
|
||||
struct qcm_process_device *qpd);
|
||||
|
@ -136,7 +136,6 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_dev *dev,
|
||||
prop.write_ptr = (uint32_t *) kq->wptr_gpu_addr;
|
||||
prop.eop_ring_buffer_address = kq->eop_gpu_addr;
|
||||
prop.eop_ring_buffer_size = PAGE_SIZE;
|
||||
prop.cu_mask = NULL;
|
||||
|
||||
if (init_queue(&kq->queue, &prop) != 0)
|
||||
goto err_init_queue;
|
||||
|
@ -80,7 +80,8 @@ struct mqd_manager {
|
||||
struct mm_struct *mms);
|
||||
|
||||
void (*update_mqd)(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q);
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo);
|
||||
|
||||
int (*destroy_mqd)(struct mqd_manager *mm, void *mqd,
|
||||
enum kfd_preempt_type type,
|
||||
|
@ -42,16 +42,17 @@ static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@ -135,7 +136,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
@ -152,7 +153,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static void free_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -185,7 +186,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q, unsigned int atc_bit)
|
||||
struct queue_properties *q, struct mqd_update_info *minfo,
|
||||
unsigned int atc_bit)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
|
||||
@ -214,16 +216,17 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (q->format == KFD_QUEUE_FORMAT_AQL)
|
||||
m->cp_hqd_pq_control |= NO_UPDATE_RPTR;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, 1);
|
||||
__update_mqd(mm, mqd, q, minfo, 1);
|
||||
}
|
||||
|
||||
static uint32_t read_doorbell_id(void *mqd)
|
||||
@ -234,13 +237,15 @@ static uint32_t read_doorbell_id(void *mqd)
|
||||
}
|
||||
|
||||
static void update_mqd_hawaii(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, 0);
|
||||
}
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_sdma_rlc_registers *m;
|
||||
|
||||
@ -318,7 +323,8 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct cik_mqd *m;
|
||||
|
||||
|
@ -42,16 +42,17 @@ static inline struct v10_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@ -136,7 +137,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -162,7 +163,8 @@ static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_compute_mqd *m;
|
||||
|
||||
@ -218,7 +220,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (mm->dev->cwsr_enabled)
|
||||
m->cp_hqd_ctx_save_control = 0;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@ -311,7 +313,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@ -326,7 +328,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
#define SDMA_RLC_DUMMY_DEFAULT 0xf
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v10_sdma_mqd *m;
|
||||
|
||||
|
@ -43,16 +43,17 @@ static inline struct v9_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
uint32_t se_mask[KFD_MAX_NUM_SE] = {0};
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@ -188,7 +189,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -212,7 +213,8 @@ static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
|
||||
@ -269,7 +271,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
if (mm->dev->cwsr_enabled && q->ctx_save_restore_area_address)
|
||||
m->cp_hqd_ctx_save_control = 0;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@ -366,7 +368,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@ -381,7 +383,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
#define SDMA_RLC_DUMMY_DEFAULT 0xf
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct v9_sdma_mqd *m;
|
||||
|
||||
|
@ -45,16 +45,17 @@ static inline struct vi_sdma_mqd *get_sdma_mqd(void *mqd)
|
||||
}
|
||||
|
||||
static void update_cu_mask(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
uint32_t se_mask[4] = {0}; /* 4 is the max # of SEs */
|
||||
|
||||
if (q->cu_mask_count == 0)
|
||||
if (!minfo || (minfo->update_flag != UPDATE_FLAG_CU_MASK) ||
|
||||
!minfo->cu_mask.ptr)
|
||||
return;
|
||||
|
||||
mqd_symmetrically_map_cu_mask(mm,
|
||||
q->cu_mask, q->cu_mask_count, se_mask);
|
||||
minfo->cu_mask.ptr, minfo->cu_mask.count, se_mask);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
m->compute_static_thread_mgmt_se0 = se_mask[0];
|
||||
@ -150,7 +151,7 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*mqd = m;
|
||||
if (gart_addr)
|
||||
*gart_addr = addr;
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -167,8 +168,8 @@ static int load_mqd(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q, unsigned int mtype,
|
||||
unsigned int atc_bit)
|
||||
struct queue_properties *q, struct mqd_update_info *minfo,
|
||||
unsigned int mtype, unsigned int atc_bit)
|
||||
{
|
||||
struct vi_mqd *m;
|
||||
|
||||
@ -230,7 +231,7 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
atc_bit << CP_HQD_CTX_SAVE_CONTROL__ATC__SHIFT |
|
||||
mtype << CP_HQD_CTX_SAVE_CONTROL__MTYPE__SHIFT;
|
||||
|
||||
update_cu_mask(mm, mqd, q);
|
||||
update_cu_mask(mm, mqd, minfo);
|
||||
set_priority(m, q);
|
||||
|
||||
q->is_active = QUEUE_IS_ACTIVE(*q);
|
||||
@ -238,9 +239,10 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
|
||||
static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_CC, 1);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_CC, 1);
|
||||
}
|
||||
|
||||
static uint32_t read_doorbell_id(void *mqd)
|
||||
@ -251,9 +253,10 @@ static uint32_t read_doorbell_id(void *mqd)
|
||||
}
|
||||
|
||||
static void update_mqd_tonga(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_UC, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_UC, 0);
|
||||
}
|
||||
|
||||
static int destroy_mqd(struct mqd_manager *mm, void *mqd,
|
||||
@ -317,9 +320,10 @@ static void init_mqd_hiq(struct mqd_manager *mm, void **mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_hiq(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
__update_mqd(mm, mqd, q, MTYPE_UC, 0);
|
||||
__update_mqd(mm, mqd, q, minfo, MTYPE_UC, 0);
|
||||
}
|
||||
|
||||
static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
@ -336,7 +340,7 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd,
|
||||
if (gart_addr)
|
||||
*gart_addr = mqd_mem_obj->gpu_addr;
|
||||
|
||||
mm->update_mqd(mm, m, q);
|
||||
mm->update_mqd(mm, m, q, NULL);
|
||||
}
|
||||
|
||||
static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
@ -349,7 +353,8 @@ static int load_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
}
|
||||
|
||||
static void update_mqd_sdma(struct mqd_manager *mm, void *mqd,
|
||||
struct queue_properties *q)
|
||||
struct queue_properties *q,
|
||||
struct mqd_update_info *minfo)
|
||||
{
|
||||
struct vi_sdma_mqd *m;
|
||||
|
||||
|
@ -472,9 +472,6 @@ struct queue_properties {
|
||||
uint32_t ctl_stack_size;
|
||||
uint64_t tba_addr;
|
||||
uint64_t tma_addr;
|
||||
/* Relevant for CU */
|
||||
uint32_t cu_mask_count; /* Must be a multiple of 32 */
|
||||
uint32_t *cu_mask;
|
||||
};
|
||||
|
||||
#define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \
|
||||
@ -482,6 +479,20 @@ struct queue_properties {
|
||||
(q).queue_percent > 0 && \
|
||||
!(q).is_evicted)
|
||||
|
||||
enum mqd_update_flag {
|
||||
UPDATE_FLAG_CU_MASK = 0,
|
||||
};
|
||||
|
||||
struct mqd_update_info {
|
||||
union {
|
||||
struct {
|
||||
uint32_t count; /* Must be a multiple of 32 */
|
||||
uint32_t *ptr;
|
||||
} cu_mask;
|
||||
};
|
||||
enum mqd_update_flag update_flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct queue
|
||||
*
|
||||
@ -608,12 +619,14 @@ struct qcm_process_device {
|
||||
uint32_t sh_hidden_private_base;
|
||||
|
||||
/* CWSR memory */
|
||||
struct kgd_mem *cwsr_mem;
|
||||
void *cwsr_kaddr;
|
||||
uint64_t cwsr_base;
|
||||
uint64_t tba_addr;
|
||||
uint64_t tma_addr;
|
||||
|
||||
/* IB memory */
|
||||
struct kgd_mem *ib_mem;
|
||||
uint64_t ib_base;
|
||||
void *ib_kaddr;
|
||||
|
||||
@ -808,6 +821,7 @@ struct kfd_process {
|
||||
/* Event ID allocator and lookup */
|
||||
struct idr event_idr;
|
||||
/* Event page */
|
||||
u64 signal_handle;
|
||||
struct kfd_signal_page *signal_page;
|
||||
size_t signal_mapped_size;
|
||||
size_t signal_event_count;
|
||||
@ -1031,10 +1045,10 @@ int pqm_create_queue(struct process_queue_manager *pqm,
|
||||
unsigned int *qid,
|
||||
uint32_t *p_doorbell_offset_in_process);
|
||||
int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid);
|
||||
int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p);
|
||||
int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
int pqm_update_queue_properties(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p);
|
||||
int pqm_update_mqd(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct mqd_update_info *minfo);
|
||||
int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
|
||||
void *gws);
|
||||
struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm,
|
||||
|
@ -72,6 +72,8 @@ static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep);
|
||||
static void evict_process_worker(struct work_struct *work);
|
||||
static void restore_process_worker(struct work_struct *work);
|
||||
|
||||
static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd);
|
||||
|
||||
struct kfd_procfs_tree {
|
||||
struct kobject *kobj;
|
||||
};
|
||||
@ -685,10 +687,15 @@ void kfd_process_destroy_wq(void)
|
||||
}
|
||||
|
||||
static void kfd_process_free_gpuvm(struct kgd_mem *mem,
|
||||
struct kfd_process_device *pdd)
|
||||
struct kfd_process_device *pdd, void *kptr)
|
||||
{
|
||||
struct kfd_dev *dev = pdd->dev;
|
||||
|
||||
if (kptr) {
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(dev->kgd, mem);
|
||||
kptr = NULL;
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(dev->kgd, mem, pdd->drm_priv);
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->kgd, mem, pdd->drm_priv,
|
||||
NULL);
|
||||
@ -702,63 +709,46 @@ static void kfd_process_free_gpuvm(struct kgd_mem *mem,
|
||||
*/
|
||||
static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
|
||||
uint64_t gpu_va, uint32_t size,
|
||||
uint32_t flags, void **kptr)
|
||||
uint32_t flags, struct kgd_mem **mem, void **kptr)
|
||||
{
|
||||
struct kfd_dev *kdev = pdd->dev;
|
||||
struct kgd_mem *mem = NULL;
|
||||
int handle;
|
||||
int err;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(kdev->kgd, gpu_va, size,
|
||||
pdd->drm_priv, &mem, NULL, flags);
|
||||
pdd->drm_priv, mem, NULL, flags);
|
||||
if (err)
|
||||
goto err_alloc_mem;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, mem,
|
||||
err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->kgd, *mem,
|
||||
pdd->drm_priv, NULL);
|
||||
if (err)
|
||||
goto err_map_mem;
|
||||
|
||||
err = amdgpu_amdkfd_gpuvm_sync_memory(kdev->kgd, mem, true);
|
||||
err = amdgpu_amdkfd_gpuvm_sync_memory(kdev->kgd, *mem, true);
|
||||
if (err) {
|
||||
pr_debug("Sync memory failed, wait interrupted by user signal\n");
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
|
||||
/* Create an obj handle so kfd_process_device_remove_obj_handle
|
||||
* will take care of the bo removal when the process finishes.
|
||||
* We do not need to take p->mutex, because the process is just
|
||||
* created and the ioctls have not had the chance to run.
|
||||
*/
|
||||
handle = kfd_process_device_create_obj_handle(pdd, mem);
|
||||
|
||||
if (handle < 0) {
|
||||
err = handle;
|
||||
goto free_gpuvm;
|
||||
}
|
||||
|
||||
if (kptr) {
|
||||
err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kdev->kgd,
|
||||
(struct kgd_mem *)mem, kptr, NULL);
|
||||
(struct kgd_mem *)*mem, kptr, NULL);
|
||||
if (err) {
|
||||
pr_debug("Map GTT BO to kernel failed\n");
|
||||
goto free_obj_handle;
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
free_obj_handle:
|
||||
kfd_process_device_remove_obj_handle(pdd, handle);
|
||||
free_gpuvm:
|
||||
sync_memory_failed:
|
||||
kfd_process_free_gpuvm(mem, pdd);
|
||||
return err;
|
||||
amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(kdev->kgd, *mem, pdd->drm_priv);
|
||||
|
||||
err_map_mem:
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(kdev->kgd, mem, pdd->drm_priv,
|
||||
amdgpu_amdkfd_gpuvm_free_memory_of_gpu(kdev->kgd, *mem, pdd->drm_priv,
|
||||
NULL);
|
||||
err_alloc_mem:
|
||||
*mem = NULL;
|
||||
*kptr = NULL;
|
||||
return err;
|
||||
}
|
||||
@ -776,6 +766,7 @@ static int kfd_process_device_reserve_ib_mem(struct kfd_process_device *pdd)
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE |
|
||||
KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
||||
struct kgd_mem *mem;
|
||||
void *kaddr;
|
||||
int ret;
|
||||
|
||||
@ -784,15 +775,26 @@ static int kfd_process_device_reserve_ib_mem(struct kfd_process_device *pdd)
|
||||
|
||||
/* ib_base is only set for dGPU */
|
||||
ret = kfd_process_alloc_gpuvm(pdd, qpd->ib_base, PAGE_SIZE, flags,
|
||||
&kaddr);
|
||||
&mem, &kaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
qpd->ib_mem = mem;
|
||||
qpd->ib_kaddr = kaddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kfd_process_device_destroy_ib_mem(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct qcm_process_device *qpd = &pdd->qpd;
|
||||
|
||||
if (!qpd->ib_kaddr || !qpd->ib_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->ib_mem, pdd, qpd->ib_kaddr);
|
||||
}
|
||||
|
||||
struct kfd_process *kfd_create_process(struct file *filep)
|
||||
{
|
||||
struct kfd_process *process;
|
||||
@ -947,6 +949,37 @@ static void kfd_process_device_free_bos(struct kfd_process_device *pdd)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Just kunmap and unpin signal BO here. It will be freed in
|
||||
* kfd_process_free_outstanding_kfd_bos()
|
||||
*/
|
||||
static void kfd_process_kunmap_signal_bo(struct kfd_process *p)
|
||||
{
|
||||
struct kfd_process_device *pdd;
|
||||
struct kfd_dev *kdev;
|
||||
void *mem;
|
||||
|
||||
kdev = kfd_device_by_id(GET_GPU_ID(p->signal_handle));
|
||||
if (!kdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
|
||||
pdd = kfd_get_process_device_data(kdev, p);
|
||||
if (!pdd)
|
||||
goto out;
|
||||
|
||||
mem = kfd_process_device_translate_handle(
|
||||
pdd, GET_IDR_HANDLE(p->signal_handle));
|
||||
if (!mem)
|
||||
goto out;
|
||||
|
||||
amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kdev->kgd, mem);
|
||||
|
||||
out:
|
||||
mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
static void kfd_process_free_outstanding_kfd_bos(struct kfd_process *p)
|
||||
{
|
||||
int i;
|
||||
@ -965,6 +998,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
|
||||
pr_debug("Releasing pdd (topology id %d) for process (pasid 0x%x)\n",
|
||||
pdd->dev->id, p->pasid);
|
||||
|
||||
kfd_process_device_destroy_cwsr_dgpu(pdd);
|
||||
kfd_process_device_destroy_ib_mem(pdd);
|
||||
|
||||
if (pdd->drm_file) {
|
||||
amdgpu_amdkfd_gpuvm_release_process_vm(
|
||||
pdd->dev->kgd, pdd->drm_priv);
|
||||
@ -1049,9 +1085,11 @@ static void kfd_process_wq_release(struct work_struct *work)
|
||||
{
|
||||
struct kfd_process *p = container_of(work, struct kfd_process,
|
||||
release_work);
|
||||
|
||||
kfd_process_remove_sysfs(p);
|
||||
kfd_iommu_unbind_process(p);
|
||||
|
||||
kfd_process_kunmap_signal_bo(p);
|
||||
kfd_process_free_outstanding_kfd_bos(p);
|
||||
svm_range_list_fini(p);
|
||||
|
||||
@ -1198,6 +1236,7 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
uint32_t flags = KFD_IOC_ALLOC_MEM_FLAGS_GTT
|
||||
| KFD_IOC_ALLOC_MEM_FLAGS_NO_SUBSTITUTE
|
||||
| KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE;
|
||||
struct kgd_mem *mem;
|
||||
void *kaddr;
|
||||
int ret;
|
||||
|
||||
@ -1206,10 +1245,11 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
|
||||
/* cwsr_base is only set for dGPU */
|
||||
ret = kfd_process_alloc_gpuvm(pdd, qpd->cwsr_base,
|
||||
KFD_CWSR_TBA_TMA_SIZE, flags, &kaddr);
|
||||
KFD_CWSR_TBA_TMA_SIZE, flags, &mem, &kaddr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
qpd->cwsr_mem = mem;
|
||||
qpd->cwsr_kaddr = kaddr;
|
||||
qpd->tba_addr = qpd->cwsr_base;
|
||||
|
||||
@ -1222,6 +1262,17 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd)
|
||||
{
|
||||
struct kfd_dev *dev = pdd->dev;
|
||||
struct qcm_process_device *qpd = &pdd->qpd;
|
||||
|
||||
if (!dev->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base)
|
||||
return;
|
||||
|
||||
kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, qpd->cwsr_kaddr);
|
||||
}
|
||||
|
||||
void kfd_process_set_trap_handler(struct qcm_process_device *qpd,
|
||||
uint64_t tba_addr,
|
||||
uint64_t tma_addr)
|
||||
|
@ -121,7 +121,7 @@ int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid,
|
||||
pdd->qpd.num_gws = gws ? amdgpu_amdkfd_get_num_gws(dev->kgd) : 0;
|
||||
|
||||
return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, NULL);
|
||||
}
|
||||
|
||||
void kfd_process_dequeue_from_all_devices(struct kfd_process *p)
|
||||
@ -394,8 +394,6 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid)
|
||||
pdd->qpd.num_gws = 0;
|
||||
}
|
||||
|
||||
kfree(pqn->q->properties.cu_mask);
|
||||
pqn->q->properties.cu_mask = NULL;
|
||||
uninit_queue(pqn->q);
|
||||
}
|
||||
|
||||
@ -411,8 +409,8 @@ err_destroy_queue:
|
||||
return retval;
|
||||
}
|
||||
|
||||
int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p)
|
||||
int pqm_update_queue_properties(struct process_queue_manager *pqm,
|
||||
unsigned int qid, struct queue_properties *p)
|
||||
{
|
||||
int retval;
|
||||
struct process_queue_node *pqn;
|
||||
@ -429,15 +427,15 @@ int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid,
|
||||
pqn->q->properties.priority = p->priority;
|
||||
|
||||
retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, NULL);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
struct queue_properties *p)
|
||||
int pqm_update_mqd(struct process_queue_manager *pqm,
|
||||
unsigned int qid, struct mqd_update_info *minfo)
|
||||
{
|
||||
int retval;
|
||||
struct process_queue_node *pqn;
|
||||
@ -448,16 +446,8 @@ int pqm_set_cu_mask(struct process_queue_manager *pqm, unsigned int qid,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Free the old CU mask memory if it is already allocated, then
|
||||
* allocate memory for the new CU mask.
|
||||
*/
|
||||
kfree(pqn->q->properties.cu_mask);
|
||||
|
||||
pqn->q->properties.cu_mask_count = p->cu_mask_count;
|
||||
pqn->q->properties.cu_mask = p->cu_mask;
|
||||
|
||||
retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm,
|
||||
pqn->q);
|
||||
pqn->q, minfo);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
|
@ -730,6 +730,8 @@ static void dm_handle_hpd_work(struct work_struct *work)
|
||||
dmub_hpd_wrk->adev->dm.dmub_callback[dmub_hpd_wrk->dmub_notify->type](dmub_hpd_wrk->adev,
|
||||
dmub_hpd_wrk->dmub_notify);
|
||||
}
|
||||
|
||||
kfree(dmub_hpd_wrk->dmub_notify);
|
||||
kfree(dmub_hpd_wrk);
|
||||
|
||||
}
|
||||
@ -755,12 +757,6 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
||||
|
||||
if (dc_enable_dmub_notifications(adev->dm.dc) &&
|
||||
irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
|
||||
do {
|
||||
dc_stat_get_dmub_notification(adev->dm.dc, ¬ify);
|
||||
@ -769,7 +765,20 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
|
||||
continue;
|
||||
}
|
||||
if (dm->dmub_thread_offload[notify.type] == true) {
|
||||
dmub_hpd_wrk->dmub_notify = ¬ify;
|
||||
dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk) {
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk");
|
||||
return;
|
||||
}
|
||||
dmub_hpd_wrk->dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_ATOMIC);
|
||||
if (!dmub_hpd_wrk->dmub_notify) {
|
||||
kfree(dmub_hpd_wrk);
|
||||
DRM_ERROR("Failed to allocate dmub_hpd_wrk->dmub_notify");
|
||||
return;
|
||||
}
|
||||
INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work);
|
||||
if (dmub_hpd_wrk->dmub_notify)
|
||||
memcpy(dmub_hpd_wrk->dmub_notify, ¬ify, sizeof(struct dmub_notification));
|
||||
dmub_hpd_wrk->adev = adev;
|
||||
if (notify.type == DMUB_NOTIFICATION_HPD) {
|
||||
plink = adev->dm.dc->links[notify.link_index];
|
||||
@ -1008,6 +1017,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
||||
const unsigned char *fw_inst_const, *fw_bss_data;
|
||||
uint32_t i, fw_inst_const_size, fw_bss_data_size;
|
||||
bool has_hw_support;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
|
||||
if (!dmub_srv)
|
||||
/* DMUB isn't supported on the ASIC. */
|
||||
@ -1094,6 +1104,19 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
|
||||
for (i = 0; i < fb_info->num_fb; ++i)
|
||||
hw_params.fb[i] = &fb_info->fb[i];
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_YELLOW_CARP:
|
||||
if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) {
|
||||
hw_params.dpia_supported = true;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
status = dmub_srv_hw_init(dmub_srv, &hw_params);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DRM_ERROR("Error initializing DMUB HW: %d\n", status);
|
||||
@ -1295,6 +1318,37 @@ static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct
|
||||
return hpd_rx_offload_wq;
|
||||
}
|
||||
|
||||
struct amdgpu_stutter_quirk {
|
||||
u16 chip_vendor;
|
||||
u16 chip_device;
|
||||
u16 subsys_vendor;
|
||||
u16 subsys_device;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
static const struct amdgpu_stutter_quirk amdgpu_stutter_quirk_list[] = {
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=214417 */
|
||||
{ 0x1002, 0x15dd, 0x1002, 0x15dd, 0xc8 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static bool dm_should_disable_stutter(struct pci_dev *pdev)
|
||||
{
|
||||
const struct amdgpu_stutter_quirk *p = amdgpu_stutter_quirk_list;
|
||||
|
||||
while (p && p->chip_device != 0) {
|
||||
if (pdev->vendor == p->chip_vendor &&
|
||||
pdev->device == p->chip_device &&
|
||||
pdev->subsystem_vendor == p->subsys_vendor &&
|
||||
pdev->subsystem_device == p->subsys_device &&
|
||||
pdev->revision == p->revision) {
|
||||
return true;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct dc_init_data init_data;
|
||||
@ -1406,6 +1460,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
|
||||
if (adev->asic_type != CHIP_CARRIZO && adev->asic_type != CHIP_STONEY)
|
||||
adev->dm.dc->debug.disable_stutter = amdgpu_pp_feature_mask & PP_STUTTER_MODE ? false : true;
|
||||
if (dm_should_disable_stutter(adev->pdev))
|
||||
adev->dm.dc->debug.disable_stutter = true;
|
||||
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
|
||||
adev->dm.dc->debug.disable_stutter = true;
|
||||
@ -1792,7 +1848,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
||||
break;
|
||||
case IP_VERSION(3, 1, 2):
|
||||
case IP_VERSION(3, 1, 3):
|
||||
dmub_asic = DMUB_ASIC_DCN31;
|
||||
dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31;
|
||||
fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
|
||||
break;
|
||||
|
||||
|
@ -491,7 +491,7 @@ static ssize_t dp_phy_settings_write(struct file *f, const char __user *buf,
|
||||
if (!wr_buf)
|
||||
return -ENOSPC;
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -643,7 +643,7 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
|
||||
if (!wr_buf)
|
||||
return -ENOSPC;
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -918,7 +918,7 @@ static ssize_t dp_dsc_passthrough_set(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
¶m, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -1215,7 +1215,7 @@ static ssize_t trigger_hotplug(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -1400,7 +1400,7 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -1585,7 +1585,7 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -1770,7 +1770,7 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -1948,7 +1948,7 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
@ -2386,7 +2386,7 @@ static ssize_t dp_max_bpc_write(struct file *f, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (parse_write_buffer_into_params(wr_buf, size,
|
||||
if (parse_write_buffer_into_params(wr_buf, wr_buf_size,
|
||||
(long *)param, buf,
|
||||
max_param_num,
|
||||
¶m_nums)) {
|
||||
|
@ -64,6 +64,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
|
||||
payload.i2c_over_aux = (msg->request & DP_AUX_NATIVE_WRITE) == 0;
|
||||
payload.write = (msg->request & DP_AUX_I2C_READ) == 0;
|
||||
payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0;
|
||||
payload.write_status_update =
|
||||
(msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0;
|
||||
payload.defer_delay = 0;
|
||||
|
||||
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
|
||||
|
@ -107,6 +107,8 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
*/
|
||||
// Init fail safe of 2 frames static
|
||||
unsigned int num_frames_static = 2;
|
||||
unsigned int power_opt = 0;
|
||||
bool psr_enable = true;
|
||||
|
||||
DRM_DEBUG_DRIVER("Enabling psr...\n");
|
||||
|
||||
@ -133,7 +135,9 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
&stream, 1,
|
||||
¶ms);
|
||||
|
||||
return dc_link_set_psr_allow_active(link, true, false, false);
|
||||
power_opt |= psr_power_opt_z10_static_screen;
|
||||
|
||||
return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -144,10 +148,12 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
|
||||
*/
|
||||
bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
|
||||
{
|
||||
unsigned int power_opt = 0;
|
||||
bool psr_enable = false;
|
||||
|
||||
DRM_DEBUG_DRIVER("Disabling psr...\n");
|
||||
|
||||
return dc_link_set_psr_allow_active(stream->link, false, true, false);
|
||||
return dc_link_set_psr_allow_active(stream->link, &psr_enable, true, false, &power_opt);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2321,6 +2321,8 @@ static enum bp_result get_integrated_info_v2_2(
|
||||
|
||||
info->ext_disp_conn_info.checksum =
|
||||
info_v2_2->extdispconninfo.checksum;
|
||||
info->ext_disp_conn_info.fixdpvoltageswing =
|
||||
info_v2_2->extdispconninfo.fixdpvoltageswing;
|
||||
|
||||
info->edp1_info.edp_backlight_pwm_hz =
|
||||
le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
|
||||
|
@ -100,11 +100,13 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
|
||||
|
||||
if (edp_num) {
|
||||
for (panel_inst = 0; panel_inst < edp_num; panel_inst++) {
|
||||
bool allow_active = false;
|
||||
|
||||
edp_link = edp_links[panel_inst];
|
||||
if (!edp_link->psr_settings.psr_feature_enabled)
|
||||
continue;
|
||||
clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active;
|
||||
dc_link_set_psr_allow_active(edp_link, false, false, false);
|
||||
dc_link_set_psr_allow_active(edp_link, &allow_active, false, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +126,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
|
||||
if (!edp_link->psr_settings.psr_feature_enabled)
|
||||
continue;
|
||||
dc_link_set_psr_allow_active(edp_link,
|
||||
clk_mgr->psr_allow_active_cache, false, false);
|
||||
&clk_mgr->psr_allow_active_cache, false, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,13 +285,8 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) {
|
||||
/* TODO: to add DCN31 clk_mgr support, once CLK IP header files are available,
|
||||
* for now use DCN3.0 clk mgr.
|
||||
*/
|
||||
dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
|
||||
dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
|
||||
return &clk_mgr->base.base;
|
||||
}
|
||||
#endif
|
||||
@ -326,7 +323,6 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
|
||||
break;
|
||||
|
||||
case FAMILY_YELLOW_CARP:
|
||||
if (ASICREV_IS_YELLOW_CARP(clk_mgr_base->ctx->asic_id.hw_internal_rev))
|
||||
dcn31_clk_mgr_destroy(clk_mgr);
|
||||
break;
|
||||
|
||||
|
@ -523,14 +523,21 @@ static unsigned int find_clk_for_voltage(
|
||||
unsigned int voltage)
|
||||
{
|
||||
int i;
|
||||
int max_voltage = 0;
|
||||
int clock = 0;
|
||||
|
||||
for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) {
|
||||
if (clock_table->SocVoltage[i] == voltage)
|
||||
if (clock_table->SocVoltage[i] == voltage) {
|
||||
return clocks[i];
|
||||
} else if (clock_table->SocVoltage[i] >= max_voltage &&
|
||||
clock_table->SocVoltage[i] < voltage) {
|
||||
max_voltage = clock_table->SocVoltage[i];
|
||||
clock = clocks[i];
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
ASSERT(clock);
|
||||
return clock;
|
||||
}
|
||||
|
||||
void dcn31_clk_mgr_helper_populate_bw_params(
|
||||
|
@ -1897,12 +1897,14 @@ static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
|
||||
static void process_deferred_updates(struct dc *dc)
|
||||
{
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN
|
||||
int i;
|
||||
int i = 0;
|
||||
|
||||
if (dc->debug.enable_mem_low_power.bits.cm)
|
||||
if (dc->debug.enable_mem_low_power.bits.cm) {
|
||||
ASSERT(dc->dcn_ip->max_num_dpp);
|
||||
for (i = 0; i < dc->dcn_ip->max_num_dpp; i++)
|
||||
if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update)
|
||||
dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2283,6 +2285,9 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
update_flags->bits.gamma_change = 1;
|
||||
}
|
||||
|
||||
if (u->lut3d_func || u->func_shaper)
|
||||
update_flags->bits.lut_3d = 1;
|
||||
|
||||
if (u->hdr_mult.value)
|
||||
if (u->hdr_mult.value != u->surface->hdr_mult.value) {
|
||||
update_flags->bits.hdr_mult = 1;
|
||||
@ -2296,6 +2301,7 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
||||
|
||||
if (update_flags->bits.input_csc_change
|
||||
|| update_flags->bits.coeff_reduction_change
|
||||
|| update_flags->bits.lut_3d
|
||||
|| update_flags->bits.gamma_change
|
||||
|| update_flags->bits.gamut_remap_change) {
|
||||
type = UPDATE_TYPE_FULL;
|
||||
@ -3493,6 +3499,7 @@ void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_
|
||||
bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
||||
{
|
||||
int i;
|
||||
bool allow_active;
|
||||
|
||||
for (i = 0; i < dc->current_state->stream_count ; i++) {
|
||||
struct dc_link *link;
|
||||
@ -3504,10 +3511,12 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
||||
|
||||
if (link->psr_settings.psr_feature_enabled) {
|
||||
if (enable && !link->psr_settings.psr_allow_active) {
|
||||
if (!dc_link_set_psr_allow_active(link, true, false, false))
|
||||
allow_active = true;
|
||||
if (!dc_link_set_psr_allow_active(link, &allow_active, false, false, NULL))
|
||||
return false;
|
||||
} else if (!enable && link->psr_settings.psr_allow_active) {
|
||||
if (!dc_link_set_psr_allow_active(link, false, true, false))
|
||||
allow_active = false;
|
||||
if (!dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -3741,6 +3750,60 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
|
||||
return is_cmd_complete;
|
||||
}
|
||||
|
||||
/**
|
||||
*****************************************************************************
|
||||
* Function: dc_process_dmub_set_mst_slots
|
||||
*
|
||||
* @brief
|
||||
* Submits mst slot allocation command to dmub via inbox message
|
||||
*
|
||||
* @param
|
||||
* [in] dc: dc structure
|
||||
* [in] link_index: link index
|
||||
* [in] mst_alloc_slots: mst slots to be allotted
|
||||
* [out] mst_slots_in_use: mst slots in use returned in failure case
|
||||
*
|
||||
* @return
|
||||
* DC_OK if successful, DC_ERROR if failure
|
||||
*****************************************************************************
|
||||
*/
|
||||
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint8_t mst_alloc_slots,
|
||||
uint8_t *mst_slots_in_use)
|
||||
{
|
||||
union dmub_rb_cmd cmd = {0};
|
||||
struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
/* prepare MST_ALLOC_SLOTS command */
|
||||
cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
|
||||
cmd.set_mst_alloc_slots.header.sub_type = DMUB_CMD__DPIA_MST_ALLOC_SLOTS;
|
||||
|
||||
cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst;
|
||||
cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots;
|
||||
|
||||
if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd))
|
||||
/* command is not processed by dmub */
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
/* command processed by dmub, if ret_status is 1 */
|
||||
if (cmd.set_config_access.header.ret_status != 1)
|
||||
/* command processing error */
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
/* command processed and we have a status of 2, mst not enabled in dpia */
|
||||
if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 2)
|
||||
return DC_FAIL_UNSUPPORTED_1;
|
||||
|
||||
/* previously configured mst alloc and used slots did not match */
|
||||
if (cmd.set_mst_alloc_slots.mst_slots_control.immed_status == 3) {
|
||||
*mst_slots_in_use = cmd.set_mst_alloc_slots.mst_slots_control.mst_slots_in_use;
|
||||
return DC_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_disable_accelerated_mode - disable accelerated mode
|
||||
* @dc: dc structure
|
||||
|
@ -1660,6 +1660,14 @@ static bool dc_link_construct_legacy(struct dc_link *link,
|
||||
DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw);
|
||||
DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps);
|
||||
}
|
||||
|
||||
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
|
||||
link->bios_forced_drive_settings.VOLTAGE_SWING =
|
||||
(info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
|
||||
link->bios_forced_drive_settings.PRE_EMPHASIS =
|
||||
((info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1757,6 +1765,9 @@ static bool dc_link_construct_dpia(struct dc_link *link,
|
||||
|
||||
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
|
||||
|
||||
/* Some docks seem to NAK I2C writes to segment pointer with mot=0. */
|
||||
link->wa_flags.dp_mot_reset_segment = true;
|
||||
|
||||
return true;
|
||||
|
||||
ddc_create_fail:
|
||||
@ -2916,8 +2927,8 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
|
||||
bool wait, bool force_static)
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
|
||||
bool wait, bool force_static, const unsigned int *power_opts)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
@ -2930,20 +2941,33 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active,
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
link->psr_settings.psr_allow_active = allow_active;
|
||||
/* Set power optimization flag */
|
||||
if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
|
||||
link->psr_settings.psr_power_opt = *power_opts;
|
||||
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
|
||||
psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt);
|
||||
}
|
||||
|
||||
/* Enable or Disable PSR */
|
||||
if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
|
||||
link->psr_settings.psr_allow_active = *allow_active;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (!allow_active)
|
||||
dc_z10_restore(dc);
|
||||
if (!link->psr_settings.psr_allow_active)
|
||||
dc_z10_restore(dc);
|
||||
#endif
|
||||
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled) {
|
||||
if (force_static && psr->funcs->psr_force_static)
|
||||
psr->funcs->psr_force_static(psr, panel_inst);
|
||||
psr->funcs->psr_enable(psr, allow_active, wait, panel_inst);
|
||||
} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled)
|
||||
dmcu->funcs->set_psr_enable(dmcu, allow_active, wait);
|
||||
else
|
||||
return false;
|
||||
if (psr != NULL && link->psr_settings.psr_feature_enabled) {
|
||||
if (force_static && psr->funcs->psr_force_static)
|
||||
psr->funcs->psr_force_static(psr, panel_inst);
|
||||
psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
|
||||
} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
|
||||
link->psr_settings.psr_feature_enabled)
|
||||
dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3475,6 +3499,20 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
|
||||
ASSERT(proposed_table.stream_count > 0);
|
||||
|
||||
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
static enum dc_status status;
|
||||
uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF;
|
||||
|
||||
for (i = 0; i < link->mst_stream_alloc_table.stream_count; i++)
|
||||
mst_alloc_slots += link->mst_stream_alloc_table.stream_allocations[i].slot_count;
|
||||
|
||||
status = dc_process_dmub_set_mst_slots(link->dc, link->link_index,
|
||||
mst_alloc_slots, &prev_mst_slots_in_use);
|
||||
ASSERT(status == DC_OK);
|
||||
DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: used_slots[%d]\n",
|
||||
status, mst_alloc_slots, prev_mst_slots_in_use);
|
||||
}
|
||||
|
||||
/* program DP source TX for payload */
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
@ -3818,6 +3856,20 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
enum dc_status status;
|
||||
uint8_t mst_alloc_slots = 0, prev_mst_slots_in_use = 0xFF;
|
||||
|
||||
for (i = 0; i < link->mst_stream_alloc_table.stream_count; i++)
|
||||
mst_alloc_slots += link->mst_stream_alloc_table.stream_allocations[i].slot_count;
|
||||
|
||||
status = dc_process_dmub_set_mst_slots(link->dc, link->link_index,
|
||||
mst_alloc_slots, &prev_mst_slots_in_use);
|
||||
ASSERT(status != DC_NOT_SUPPORTED);
|
||||
DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: used_slots[%d]\n",
|
||||
status, mst_alloc_slots, prev_mst_slots_in_use);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
switch (dp_get_link_encoding_format(&link->cur_link_settings)) {
|
||||
case DP_8b_10b_ENCODING:
|
||||
@ -3861,6 +3913,9 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
|
||||
struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
struct link_encoder *link_enc = NULL;
|
||||
struct dc_state *state = pipe_ctx->stream->ctx->dc->current_state;
|
||||
struct link_enc_assignment link_enc_assign;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (cp_psp && cp_psp->funcs.update_stream_config) {
|
||||
@ -3874,9 +3929,72 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
|
||||
config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY) {
|
||||
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY ||
|
||||
pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
link_enc = pipe_ctx->stream->link->link_enc;
|
||||
config.dio_output_type = pipe_ctx->stream->link->ep_type;
|
||||
config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY)
|
||||
link_enc = pipe_ctx->stream->link->link_enc;
|
||||
else if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
|
||||
if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) {
|
||||
link_enc = link_enc_cfg_get_link_enc_used_by_stream(
|
||||
pipe_ctx->stream->ctx->dc,
|
||||
pipe_ctx->stream);
|
||||
}
|
||||
// Initialize PHY ID with ABCDE - 01234 mapping except when it is B0
|
||||
config.phy_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
|
||||
//look up the link_enc_assignment for the current pipe_ctx
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (pipe_ctx->stream == state->streams[i]) {
|
||||
link_enc_assign = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
|
||||
}
|
||||
}
|
||||
// Add flag to guard new A0 DIG mapping
|
||||
if (pipe_ctx->stream->ctx->dc->enable_c20_dtm_b0 == true) {
|
||||
config.dig_be = link_enc_assign.eng_id;
|
||||
config.dio_output_type = pipe_ctx->stream->link->ep_type;
|
||||
config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
|
||||
} else {
|
||||
config.dio_output_type = 0;
|
||||
config.dio_output_idx = 0;
|
||||
}
|
||||
|
||||
// Add flag to guard B0 implementation
|
||||
if (pipe_ctx->stream->ctx->dc->enable_c20_dtm_b0 == true &&
|
||||
link_enc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
|
||||
if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
|
||||
link_enc = link_enc_assign.stream->link_enc;
|
||||
|
||||
// enum ID 1-4 maps to DPIA PHY ID 0-3
|
||||
config.phy_idx = link_enc_assign.ep_id.link_id.enum_id - ENUM_ID_1;
|
||||
} else { // for non DPIA mode over B0, ABCDE maps to 01564
|
||||
|
||||
switch (link_enc->transmitter) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
config.phy_idx = 0;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
config.phy_idx = 1;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
config.phy_idx = 5;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
config.phy_idx = 6;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
config.phy_idx = 4;
|
||||
break;
|
||||
default:
|
||||
config.phy_idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) {
|
||||
link_enc = link_enc_cfg_get_link_enc_used_by_stream(
|
||||
pipe_ctx->stream->ctx->dc,
|
||||
|
@ -554,6 +554,7 @@ bool dal_ddc_service_query_ddc_data(
|
||||
payload.address = address;
|
||||
payload.reply = NULL;
|
||||
payload.defer_delay = get_defer_delay(ddc);
|
||||
payload.write_status_update = false;
|
||||
|
||||
if (write_size != 0) {
|
||||
payload.write = true;
|
||||
@ -625,24 +626,24 @@ bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
|
||||
do {
|
||||
struct aux_payload current_payload;
|
||||
bool is_end_of_payload = (retrieved + DEFAULT_AUX_MAX_DATA_SIZE) >=
|
||||
payload->length;
|
||||
payload->length ? true : false;
|
||||
uint32_t payload_length = is_end_of_payload ?
|
||||
payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
|
||||
|
||||
current_payload.address = payload->address;
|
||||
current_payload.data = &payload->data[retrieved];
|
||||
current_payload.defer_delay = payload->defer_delay;
|
||||
current_payload.i2c_over_aux = payload->i2c_over_aux;
|
||||
current_payload.length = is_end_of_payload ?
|
||||
payload->length - retrieved : DEFAULT_AUX_MAX_DATA_SIZE;
|
||||
/* set mot (middle of transaction) to false
|
||||
* if it is the last payload
|
||||
*/
|
||||
current_payload.length = payload_length;
|
||||
/* set mot (middle of transaction) to false if it is the last payload */
|
||||
current_payload.mot = is_end_of_payload ? payload->mot:true;
|
||||
current_payload.write_status_update = false;
|
||||
current_payload.reply = payload->reply;
|
||||
current_payload.write = payload->write;
|
||||
|
||||
ret = dc_link_aux_transfer_with_retries(ddc, ¤t_payload);
|
||||
|
||||
retrieved += current_payload.length;
|
||||
retrieved += payload_length;
|
||||
} while (retrieved < payload->length && ret == true);
|
||||
|
||||
return ret;
|
||||
|
@ -106,6 +106,10 @@ static bool decide_fallback_link_setting(
|
||||
static struct dc_link_settings get_common_supported_link_settings(
|
||||
struct dc_link_settings link_setting_a,
|
||||
struct dc_link_settings link_setting_b);
|
||||
static void maximize_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
|
||||
static void override_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
|
||||
|
||||
static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
|
||||
const struct dc_link_settings *link_settings)
|
||||
@ -515,8 +519,6 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
enum dc_dp_training_pattern pattern,
|
||||
uint32_t offset)
|
||||
{
|
||||
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
uint32_t dpcd_base_lt_offset;
|
||||
|
||||
uint8_t dpcd_lt_buffer[5] = {0};
|
||||
@ -554,16 +556,14 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
|
||||
}
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->lane_settings, dpcd_lane);
|
||||
|
||||
/* concatenate everything into one buffer*/
|
||||
|
||||
size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
|
||||
size_in_bytes = lt_settings->link_settings.lane_count *
|
||||
sizeof(lt_settings->dpcd_lane_settings[0]);
|
||||
|
||||
// 0x00103 - 0x00102
|
||||
memmove(
|
||||
&dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],
|
||||
dpcd_lane,
|
||||
lt_settings->dpcd_lane_settings,
|
||||
size_in_bytes);
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
@ -575,7 +575,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
@ -584,10 +584,10 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
} else {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
@ -595,17 +595,17 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
|
||||
__func__,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
|
||||
__func__,
|
||||
dpcd_base_lt_offset,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
}
|
||||
if (edp_workaround) {
|
||||
/* for eDP write in 2 parts because the 5-byte burst is
|
||||
@ -620,7 +620,7 @@ static void dpcd_set_lt_pattern_and_lane_settings(
|
||||
core_link_write_dpcd(
|
||||
link,
|
||||
DP_TRAINING_LANE0_SET,
|
||||
(uint8_t *)(dpcd_lane),
|
||||
(uint8_t *)(lt_settings->dpcd_lane_settings),
|
||||
size_in_bytes);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@ -711,34 +711,44 @@ void dp_hw_to_dpcd_lane_settings(
|
||||
}
|
||||
}
|
||||
|
||||
void dp_update_drive_settings(
|
||||
struct link_training_settings *dest,
|
||||
struct link_training_settings src)
|
||||
void dp_decide_lane_settings(
|
||||
const struct link_training_settings *lt_settings,
|
||||
const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
|
||||
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
for (lane = 0; lane < src.link_settings.lane_count; lane++) {
|
||||
if (dest->voltage_swing == NULL)
|
||||
dest->lane_settings[lane].VOLTAGE_SWING = src.lane_settings[lane].VOLTAGE_SWING;
|
||||
else
|
||||
dest->lane_settings[lane].VOLTAGE_SWING = *dest->voltage_swing;
|
||||
|
||||
if (dest->pre_emphasis == NULL)
|
||||
dest->lane_settings[lane].PRE_EMPHASIS = src.lane_settings[lane].PRE_EMPHASIS;
|
||||
else
|
||||
dest->lane_settings[lane].PRE_EMPHASIS = *dest->pre_emphasis;
|
||||
|
||||
if (dest->post_cursor2 == NULL)
|
||||
dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2;
|
||||
else
|
||||
dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2;
|
||||
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
hw_lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(ln_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
hw_lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(ln_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
}
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dest->ffe_preset == NULL)
|
||||
dest->lane_settings[lane].FFE_PRESET = src.lane_settings[lane].FFE_PRESET;
|
||||
else
|
||||
dest->lane_settings[lane].FFE_PRESET = *dest->ffe_preset;
|
||||
else if (dp_get_link_encoding_format(<_settings->link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
hw_lane_settings[lane].FFE_PRESET.raw =
|
||||
ln_adjust[lane].tx_ffe.PRESET_VALUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
|
||||
|
||||
if (lt_settings->disallow_per_lane_settings) {
|
||||
/* we find the maximum of the requested settings across all lanes*/
|
||||
/* and set this maximum for all lanes*/
|
||||
maximize_lane_settings(lt_settings, hw_lane_settings);
|
||||
override_lane_settings(lt_settings, hw_lane_settings);
|
||||
|
||||
if (lt_settings->always_match_dpcd_with_hw_lane_settings)
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static uint8_t get_nibble_at_index(const uint8_t *buf,
|
||||
@ -768,55 +778,29 @@ static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
|
||||
|
||||
}
|
||||
|
||||
static void find_max_drive_settings(
|
||||
const struct link_training_settings *link_training_setting,
|
||||
struct link_training_settings *max_lt_setting)
|
||||
static void maximize_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
struct dc_lane_settings max_requested;
|
||||
|
||||
max_requested.VOLTAGE_SWING =
|
||||
link_training_setting->
|
||||
lane_settings[0].VOLTAGE_SWING;
|
||||
max_requested.PRE_EMPHASIS =
|
||||
link_training_setting->
|
||||
lane_settings[0].PRE_EMPHASIS;
|
||||
/*max_requested.postCursor2 =
|
||||
* link_training_setting->laneSettings[0].postCursor2;*/
|
||||
max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
|
||||
max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
max_requested.FFE_PRESET =
|
||||
link_training_setting->lane_settings[0].FFE_PRESET;
|
||||
max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
|
||||
#endif
|
||||
|
||||
/* Determine what the maximum of the requested settings are*/
|
||||
for (lane = 1; lane < link_training_setting->link_settings.lane_count;
|
||||
lane++) {
|
||||
if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
|
||||
max_requested.VOLTAGE_SWING)
|
||||
for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
|
||||
if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
|
||||
max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
|
||||
|
||||
max_requested.VOLTAGE_SWING =
|
||||
link_training_setting->
|
||||
lane_settings[lane].VOLTAGE_SWING;
|
||||
|
||||
if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
|
||||
max_requested.PRE_EMPHASIS)
|
||||
max_requested.PRE_EMPHASIS =
|
||||
link_training_setting->
|
||||
lane_settings[lane].PRE_EMPHASIS;
|
||||
|
||||
/*
|
||||
if (link_training_setting->laneSettings[lane].postCursor2 >
|
||||
max_requested.postCursor2)
|
||||
{
|
||||
max_requested.postCursor2 =
|
||||
link_training_setting->laneSettings[lane].postCursor2;
|
||||
}
|
||||
*/
|
||||
if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
|
||||
max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (link_training_setting->lane_settings[lane].FFE_PRESET.settings.level >
|
||||
if (lane_settings[lane].FFE_PRESET.settings.level >
|
||||
max_requested.FFE_PRESET.settings.level)
|
||||
max_requested.FFE_PRESET.settings.level =
|
||||
link_training_setting->
|
||||
lane_settings[lane].FFE_PRESET.settings.level;
|
||||
#endif
|
||||
}
|
||||
@ -828,10 +812,6 @@ static void find_max_drive_settings(
|
||||
|
||||
if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
|
||||
max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
|
||||
/*
|
||||
if (max_requested.postCursor2 > PostCursor2_MaxLevel)
|
||||
max_requested.postCursor2 = PostCursor2_MaxLevel;
|
||||
*/
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
|
||||
max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
|
||||
@ -845,61 +825,58 @@ static void find_max_drive_settings(
|
||||
get_max_pre_emphasis_for_voltage_swing(
|
||||
max_requested.VOLTAGE_SWING);
|
||||
|
||||
/*
|
||||
* Post Cursor2 levels are completely independent from
|
||||
* pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
|
||||
* can only be applied to each allowable combination of voltage
|
||||
* swing and pre-emphasis levels */
|
||||
/* if ( max_requested.postCursor2 >
|
||||
* getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
|
||||
* max_requested.postCursor2 =
|
||||
* getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
|
||||
*/
|
||||
|
||||
max_lt_setting->link_settings.link_rate =
|
||||
link_training_setting->link_settings.link_rate;
|
||||
max_lt_setting->link_settings.lane_count =
|
||||
link_training_setting->link_settings.lane_count;
|
||||
max_lt_setting->link_settings.link_spread =
|
||||
link_training_setting->link_settings.link_spread;
|
||||
|
||||
for (lane = 0; lane <
|
||||
link_training_setting->link_settings.lane_count;
|
||||
lane++) {
|
||||
max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
|
||||
max_requested.VOLTAGE_SWING;
|
||||
max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
|
||||
max_requested.PRE_EMPHASIS;
|
||||
/*max_lt_setting->laneSettings[lane].postCursor2 =
|
||||
* max_requested.postCursor2;
|
||||
*/
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
|
||||
lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
max_lt_setting->lane_settings[lane].FFE_PRESET =
|
||||
max_requested.FFE_PRESET;
|
||||
lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
static void override_lane_settings(const struct link_training_settings *lt_settings,
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
|
||||
{
|
||||
uint32_t lane;
|
||||
|
||||
if (lt_settings->voltage_swing == NULL &&
|
||||
lt_settings->pre_emphasis == NULL &&
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
lt_settings->ffe_preset == NULL &&
|
||||
#endif
|
||||
lt_settings->post_cursor2 == NULL)
|
||||
|
||||
return;
|
||||
|
||||
for (lane = 1; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
if (lt_settings->voltage_swing)
|
||||
lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
|
||||
if (lt_settings->pre_emphasis)
|
||||
lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
|
||||
if (lt_settings->post_cursor2)
|
||||
lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (lt_settings->ffe_preset)
|
||||
lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
enum dc_status dp_get_lane_status_and_lane_adjust(
|
||||
struct dc_link *link,
|
||||
const struct link_training_settings *link_training_setting,
|
||||
union lane_status *ln_status,
|
||||
union lane_align_status_updated *ln_status_updated,
|
||||
struct link_training_settings *req_settings,
|
||||
union lane_status ln_status[LANE_COUNT_DP_MAX],
|
||||
union lane_align_status_updated *ln_align,
|
||||
union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
uint32_t offset)
|
||||
{
|
||||
unsigned int lane01_status_address = DP_LANE0_1_STATUS;
|
||||
uint8_t lane_adjust_offset = 4;
|
||||
unsigned int lane01_adjust_address;
|
||||
uint8_t dpcd_buf[6] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
struct link_training_settings request_settings = { {0} };
|
||||
uint32_t lane;
|
||||
enum dc_status status;
|
||||
|
||||
memset(req_settings, '\0', sizeof(struct link_training_settings));
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
lane01_status_address =
|
||||
DP_LANE0_1_STATUS_PHY_REPEATER1 +
|
||||
@ -919,11 +896,11 @@ enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
|
||||
ln_status[lane].raw =
|
||||
get_nibble_at_index(&dpcd_buf[0], lane);
|
||||
dpcd_lane_adjust[lane].raw =
|
||||
ln_adjust[lane].raw =
|
||||
get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
|
||||
}
|
||||
|
||||
ln_status_updated->raw = dpcd_buf[2];
|
||||
ln_align->raw = dpcd_buf[2];
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"
|
||||
@ -962,55 +939,6 @@ enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
dpcd_buf[lane_adjust_offset + 1]);
|
||||
}
|
||||
|
||||
/*copy to req_settings*/
|
||||
request_settings.link_settings.lane_count =
|
||||
link_training_setting->link_settings.lane_count;
|
||||
request_settings.link_settings.link_rate =
|
||||
link_training_setting->link_settings.link_rate;
|
||||
request_settings.link_settings.link_spread =
|
||||
link_training_setting->link_settings.link_spread;
|
||||
|
||||
for (lane = 0; lane <
|
||||
(uint32_t)(link_training_setting->link_settings.lane_count);
|
||||
lane++) {
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
request_settings.lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust[lane].tx_ffe.PRESET_VALUE;
|
||||
} else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
request_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
request_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
}
|
||||
#else
|
||||
request_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
|
||||
VOLTAGE_SWING_LANE);
|
||||
request_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
|
||||
PRE_EMPHASIS_LANE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Note: for postcursor2, read adjusted
|
||||
* postcursor2 settings from*/
|
||||
/*DpcdAddress_AdjustRequestPostCursor2 =
|
||||
*0x020C (not implemented yet)*/
|
||||
|
||||
/* we find the maximum of the requested settings across all lanes*/
|
||||
/* and set this maximum for all lanes*/
|
||||
find_max_drive_settings(&request_settings, req_settings);
|
||||
|
||||
/* if post cursor 2 is needed in the future,
|
||||
* read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
|
||||
*/
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1019,7 +947,6 @@ enum dc_status dpcd_set_lane_settings(
|
||||
const struct link_training_settings *link_training_setting,
|
||||
uint32_t offset)
|
||||
{
|
||||
union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
|
||||
unsigned int lane0_set_address;
|
||||
enum dc_status status;
|
||||
|
||||
@ -1029,34 +956,11 @@ enum dc_status dpcd_set_lane_settings(
|
||||
lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 +
|
||||
((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1));
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(link_training_setting,
|
||||
link_training_setting->lane_settings,
|
||||
dpcd_lane);
|
||||
|
||||
status = core_link_write_dpcd(link,
|
||||
lane0_set_address,
|
||||
(uint8_t *)(dpcd_lane),
|
||||
(uint8_t *)(link_training_setting->dpcd_lane_settings),
|
||||
link_training_setting->link_settings.lane_count);
|
||||
|
||||
/*
|
||||
if (LTSettings.link.rate == LinkRate_High2)
|
||||
{
|
||||
DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
|
||||
for ( uint32_t lane = 0;
|
||||
lane < lane_count_DPMax; lane++)
|
||||
{
|
||||
dpcd_lane2[lane].bits.post_cursor2_set =
|
||||
static_cast<unsigned char>(
|
||||
LTSettings.laneSettings[lane].postCursor2);
|
||||
dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
|
||||
}
|
||||
m_pDpcdAccessSrv->WriteDpcdData(
|
||||
DpcdAddress_Lane0Set2,
|
||||
reinterpret_cast<unsigned char*>(dpcd_lane2),
|
||||
LTSettings.link.lanes);
|
||||
}
|
||||
*/
|
||||
|
||||
if (is_repeater(link, offset)) {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
@ -1066,7 +970,7 @@ enum dc_status dpcd_set_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
@ -1075,10 +979,10 @@ enum dc_status dpcd_set_lane_settings(
|
||||
__func__,
|
||||
offset,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
|
||||
} else {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@ -1087,17 +991,17 @@ enum dc_status dpcd_set_lane_settings(
|
||||
DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",
|
||||
__func__,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].tx_ffe.PRESET_VALUE);
|
||||
link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE);
|
||||
else if (dp_get_link_encoding_format(&link_training_setting->link_settings) ==
|
||||
DP_8b_10b_ENCODING)
|
||||
#endif
|
||||
DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",
|
||||
__func__,
|
||||
lane0_set_address,
|
||||
dpcd_lane[0].bits.VOLTAGE_SWING_SET,
|
||||
dpcd_lane[0].bits.PRE_EMPHASIS_SET,
|
||||
dpcd_lane[0].bits.MAX_SWING_REACHED,
|
||||
dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,
|
||||
link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -1110,7 +1014,7 @@ bool dp_is_max_vs_reached(
|
||||
for (lane = 0; lane <
|
||||
(uint32_t)(lt_settings->link_settings.lane_count);
|
||||
lane++) {
|
||||
if (lt_settings->lane_settings[lane].VOLTAGE_SWING
|
||||
if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
|
||||
== VOLTAGE_SWING_MAX_LEVEL)
|
||||
return true;
|
||||
}
|
||||
@ -1140,17 +1044,17 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
|
||||
adj_req_timer++) {
|
||||
|
||||
struct link_training_settings req_settings;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
|
||||
union lane_align_status_updated
|
||||
dpcd_lane_status_updated;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
|
||||
if (dpcd_lane_status_updated.bits.
|
||||
@ -1168,11 +1072,10 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
|
||||
|
||||
if (lt_settings->
|
||||
lane_settings[lane].VOLTAGE_SWING !=
|
||||
req_settings.lane_settings[lane].
|
||||
VOLTAGE_SWING ||
|
||||
lt_settings->lane_settings[lane].PRE_EMPHASIS !=
|
||||
req_settings.lane_settings[lane].PRE_EMPHASIS) {
|
||||
dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
|
||||
dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
|
||||
lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
|
||||
dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
|
||||
|
||||
req_drv_setting_changed = true;
|
||||
break;
|
||||
@ -1180,8 +1083,8 @@ static bool perform_post_lt_adj_req_sequence(
|
||||
}
|
||||
|
||||
if (req_drv_setting_changed) {
|
||||
dp_update_drive_settings(
|
||||
lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
dc_link_dp_set_drive_settings(link,
|
||||
lt_settings);
|
||||
@ -1261,16 +1164,15 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
struct link_training_settings *lt_settings,
|
||||
uint32_t offset)
|
||||
{
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_dp_training_pattern tr_pattern;
|
||||
uint32_t retries_ch_eq;
|
||||
uint32_t wait_time_microsec;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
|
||||
|
||||
/* Note: also check that TPS4 is a supported feature*/
|
||||
|
||||
tr_pattern = lt_settings->pattern_for_eq;
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@ -1316,12 +1218,12 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
/* 4. Read lane status and requested
|
||||
* drive settings as set by the sink*/
|
||||
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
offset);
|
||||
|
||||
/* 5. check CR done*/
|
||||
@ -1335,7 +1237,8 @@ static enum link_training_result perform_channel_equalization_sequence(
|
||||
return LINK_TRAINING_SUCCESS;
|
||||
|
||||
/* 7. update VS/PE/PC2 in lt_settings*/
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
return LINK_TRAINING_EQ_FAIL_EQ;
|
||||
@ -1361,10 +1264,10 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
uint32_t retries_cr;
|
||||
uint32_t retry_count;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
|
||||
union lane_align_status_updated dpcd_lane_status_updated;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
retries_cr = 0;
|
||||
retry_count = 0;
|
||||
@ -1418,12 +1321,12 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
/* 4. Read lane status and requested drive
|
||||
* settings as set by the sink
|
||||
*/
|
||||
dp_get_lane_status_and_drive_settings(
|
||||
dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
offset);
|
||||
|
||||
/* 5. check CR done*/
|
||||
@ -1441,33 +1344,25 @@ static enum link_training_result perform_clock_recovery_sequence(
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
|
||||
lt_settings->lane_settings[0].FFE_PRESET.settings.level ==
|
||||
req_settings.lane_settings[0].FFE_PRESET.settings.level)
|
||||
retries_cr++;
|
||||
else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
|
||||
lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING)
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
#else
|
||||
/* 7. same lane settings*/
|
||||
/* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient*/
|
||||
if ((lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING)
|
||||
&& (lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS))
|
||||
if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) &&
|
||||
lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
retries_cr++;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) &&
|
||||
lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
|
||||
dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
|
||||
retries_cr++;
|
||||
#endif
|
||||
else
|
||||
retries_cr = 0;
|
||||
#endif
|
||||
|
||||
/* 8. update VS/PE/PC2 in lt_settings*/
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@ -1596,6 +1491,9 @@ static inline void decide_8b_10b_training_settings(
|
||||
lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
|
||||
lt_settings->enhanced_framing = 1;
|
||||
lt_settings->should_set_fec_ready = true;
|
||||
lt_settings->disallow_per_lane_settings = true;
|
||||
lt_settings->always_match_dpcd_with_hw_lane_settings = true;
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
@ -1621,6 +1519,9 @@ static inline void decide_128b_132b_training_settings(struct dc_link *link,
|
||||
link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
|
||||
lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ?
|
||||
LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT;
|
||||
lt_settings->disallow_per_lane_settings = true;
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1661,7 +1562,13 @@ static void override_training_settings(
|
||||
if (overrides->ffe_preset != NULL)
|
||||
lt_settings->ffe_preset = overrides->ffe_preset;
|
||||
#endif
|
||||
|
||||
/* Override HW lane settings with BIOS forced values if present */
|
||||
if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
|
||||
link->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
|
||||
lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
|
||||
lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
|
||||
lt_settings->always_match_dpcd_with_hw_lane_settings = false;
|
||||
}
|
||||
for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
|
||||
lt_settings->lane_settings[lane].VOLTAGE_SWING =
|
||||
lt_settings->voltage_swing != NULL ?
|
||||
@ -1677,6 +1584,9 @@ static void override_training_settings(
|
||||
: POST_CURSOR2_DISABLED;
|
||||
}
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
/* Initialize training timings */
|
||||
if (overrides->cr_pattern_time != NULL)
|
||||
lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
|
||||
@ -1947,6 +1857,9 @@ void dc_link_dp_set_drive_settings(
|
||||
/* program ASIC PHY settings*/
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
|
||||
dp_hw_to_dpcd_lane_settings(lt_settings,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
|
||||
/* Notify DP sink the PHY settings from source */
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
}
|
||||
@ -2074,38 +1987,43 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
struct dc_link *link,
|
||||
struct link_training_settings *lt_settings)
|
||||
{
|
||||
uint8_t loop_count = 0;
|
||||
uint8_t loop_count;
|
||||
uint32_t aux_rd_interval = 0;
|
||||
uint32_t wait_time = 0;
|
||||
struct link_training_settings req_settings;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
enum link_training_result status = LINK_TRAINING_SUCCESS;
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
|
||||
|
||||
/* Transmit 128b/132b_TPS1 over Main-Link and Set TRAINING_PATTERN_SET to 01h */
|
||||
/* Transmit 128b/132b_TPS1 over Main-Link */
|
||||
dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, DPRX);
|
||||
/* Set TRAINING_PATTERN_SET to 01h */
|
||||
dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
|
||||
|
||||
/* Adjust TX_FFE_PRESET_VALUE as requested */
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
/* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
|
||||
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
|
||||
/* Transmit 128b/132b_TPS2 over Main-Link and Set TRAINING_PATTERN_SET to 02h */
|
||||
dp_set_hw_training_pattern(link, lt_settings->pattern_for_eq, DPRX);
|
||||
dpcd_set_training_pattern(link, lt_settings->pattern_for_eq);
|
||||
|
||||
/* Set loop counter to start from 1 */
|
||||
loop_count = 1;
|
||||
|
||||
/* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
|
||||
dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
|
||||
lt_settings->pattern_for_eq, DPRX);
|
||||
|
||||
/* poll for channel EQ done */
|
||||
while (status == LINK_TRAINING_SUCCESS) {
|
||||
loop_count++;
|
||||
dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
|
||||
wait_time += aux_rd_interval;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
|
||||
if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
|
||||
dpcd_lane_status)) {
|
||||
@ -2119,6 +2037,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
dp_set_hw_lane_settings(link, lt_settings, DPRX);
|
||||
dpcd_set_lane_settings(link, lt_settings, DPRX);
|
||||
}
|
||||
loop_count++;
|
||||
}
|
||||
|
||||
/* poll for EQ interlane align done */
|
||||
@ -2134,8 +2053,8 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
|
||||
dp_wait_for_training_aux_rd_interval(link,
|
||||
lt_settings->eq_pattern_time);
|
||||
wait_time += lt_settings->eq_pattern_time;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2148,9 +2067,9 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
|
||||
{
|
||||
/* Assumption: assume hardware has transmitted eq pattern */
|
||||
enum link_training_result status = LINK_TRAINING_SUCCESS;
|
||||
struct link_training_settings req_settings;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = {0};
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint32_t wait_time = 0;
|
||||
|
||||
/* initiate CDS done sequence */
|
||||
@ -2161,8 +2080,8 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
|
||||
dp_wait_for_training_aux_rd_interval(link,
|
||||
lt_settings->cds_pattern_time);
|
||||
wait_time += lt_settings->cds_pattern_time;
|
||||
dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, &req_settings, DPRX);
|
||||
dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
|
||||
&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
|
||||
if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
|
||||
dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
|
||||
/* pass */
|
||||
@ -2219,7 +2138,7 @@ static enum link_training_result dp_perform_8b_10b_link_training(
|
||||
}
|
||||
|
||||
for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++)
|
||||
lt_settings->lane_settings[lane].VOLTAGE_SWING = VOLTAGE_SWING_LEVEL0;
|
||||
lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET = VOLTAGE_SWING_LEVEL0;
|
||||
}
|
||||
|
||||
if (status == LINK_TRAINING_SUCCESS) {
|
||||
@ -3523,6 +3442,8 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
|
||||
if (psr_error_status.bits.LINK_CRC_ERROR ||
|
||||
psr_error_status.bits.RFB_STORAGE_ERROR ||
|
||||
psr_error_status.bits.VSC_SDP_ERROR) {
|
||||
bool allow_active;
|
||||
|
||||
/* Acknowledge and clear error bits */
|
||||
dm_helpers_dp_write_dpcd(
|
||||
link->ctx,
|
||||
@ -3532,8 +3453,10 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link)
|
||||
sizeof(psr_error_status.raw));
|
||||
|
||||
/* PSR error, disable and re-enable PSR */
|
||||
dc_link_set_psr_allow_active(link, false, true, false);
|
||||
dc_link_set_psr_allow_active(link, true, true, false);
|
||||
allow_active = false;
|
||||
dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
|
||||
allow_active = true;
|
||||
dc_link_set_psr_allow_active(link, &allow_active, true, false, NULL);
|
||||
|
||||
return true;
|
||||
} else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
|
||||
@ -3591,15 +3514,13 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||
#endif
|
||||
unsigned int test_pattern_size = 0;
|
||||
enum dp_test_pattern test_pattern;
|
||||
struct dc_link_training_settings link_settings;
|
||||
union lane_adjust dpcd_lane_adjust;
|
||||
unsigned int lane;
|
||||
struct link_training_settings link_training_settings;
|
||||
int i = 0;
|
||||
|
||||
dpcd_test_pattern.raw = 0;
|
||||
memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
|
||||
memset(&link_settings, 0, sizeof(link_settings));
|
||||
memset(&link_training_settings, 0, sizeof(link_training_settings));
|
||||
|
||||
/* get phy test pattern and pattern parameters from DP receiver */
|
||||
core_link_read_dpcd(
|
||||
@ -3720,48 +3641,37 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
|
||||
#endif
|
||||
|
||||
/* prepare link training settings */
|
||||
link_settings.link = link->cur_link_settings;
|
||||
link_training_settings.link_settings = link->cur_link_settings;
|
||||
|
||||
for (lane = 0; lane <
|
||||
(unsigned int)(link->cur_link_settings.lane_count);
|
||||
lane++) {
|
||||
dpcd_lane_adjust.raw =
|
||||
get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
link_settings.lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
|
||||
} else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_8b_10b_ENCODING) {
|
||||
link_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)
|
||||
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
|
||||
link_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)
|
||||
(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
|
||||
link_settings.lane_settings[lane].POST_CURSOR2 =
|
||||
link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
|
||||
(enum dc_post_cursor2)
|
||||
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
|
||||
}
|
||||
#else
|
||||
link_settings.lane_settings[lane].VOLTAGE_SWING =
|
||||
(enum dc_voltage_swing)
|
||||
(dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
|
||||
link_settings.lane_settings[lane].PRE_EMPHASIS =
|
||||
(enum dc_pre_emphasis)
|
||||
(dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
|
||||
link_settings.lane_settings[lane].POST_CURSOR2 =
|
||||
(enum dc_post_cursor2)
|
||||
((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
|
||||
DP_128b_132b_ENCODING) {
|
||||
link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
|
||||
dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
link_training_settings.lane_settings[i] =
|
||||
link_settings.lane_settings[i];
|
||||
link_training_settings.link_settings = link_settings.link;
|
||||
link_training_settings.allow_invalid_msa_timing_param = false;
|
||||
dp_hw_to_dpcd_lane_settings(&link_training_settings,
|
||||
link_training_settings.hw_lane_settings,
|
||||
link_training_settings.dpcd_lane_settings);
|
||||
/*Usage: Measure DP physical lane signal
|
||||
* by DP SI test equipment automatically.
|
||||
* PHY test pattern request is generated by equipment via HPD interrupt.
|
||||
|
@ -263,10 +263,10 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
uint32_t retry_count = 0;
|
||||
/* From DP spec, CR read interval is always 100us. */
|
||||
uint32_t wait_time_microsec = TRAINING_AUX_RD_INTERVAL;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint8_t set_cfg_data;
|
||||
enum dpia_set_config_ts ts;
|
||||
|
||||
@ -345,11 +345,12 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
hop);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@ -371,16 +372,18 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link
|
||||
* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient.
|
||||
*/
|
||||
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING &&
|
||||
lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS)
|
||||
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
|
||||
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->lane_settings,
|
||||
lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@ -416,10 +419,10 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */
|
||||
uint32_t retry_count = 0;
|
||||
uint32_t wait_time_microsec = lt_settings->cr_pattern_time;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
/* Cap of LINK_TRAINING_MAX_CR_RETRY attempts at clock recovery.
|
||||
* Fix inherited from perform_clock_recovery_sequence() -
|
||||
@ -445,11 +448,12 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@ -471,16 +475,17 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li
|
||||
* Note: settings are the same for all lanes,
|
||||
* so comparing first lane is sufficient.
|
||||
*/
|
||||
if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
|
||||
req_settings.lane_settings[0].VOLTAGE_SWING &&
|
||||
lt_settings->lane_settings[0].PRE_EMPHASIS ==
|
||||
req_settings.lane_settings[0].PRE_EMPHASIS)
|
||||
if ((lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
|
||||
dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
|
||||
&& (lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET ==
|
||||
dpcd_lane_adjust[0].bits.PRE_EMPHASIS_LANE))
|
||||
retries_cr++;
|
||||
else
|
||||
retries_cr = 0;
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
@ -566,10 +571,10 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
enum dc_status status;
|
||||
enum dc_dp_training_pattern tr_pattern;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
uint8_t set_cfg_data;
|
||||
enum dpia_set_config_ts ts;
|
||||
|
||||
@ -639,11 +644,12 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
hop);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@ -664,7 +670,8 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link
|
||||
}
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
/* Abort link training if equalization failed due to HPD unplug. */
|
||||
@ -701,10 +708,10 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
enum dc_status status;
|
||||
enum dc_dp_training_pattern tr_pattern = lt_settings->pattern_for_eq;
|
||||
uint32_t wait_time_microsec;
|
||||
struct link_training_settings req_settings;
|
||||
enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
|
||||
union lane_align_status_updated dpcd_lane_status_updated = { {0} };
|
||||
union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
|
||||
|
||||
wait_time_microsec = dpia_get_eq_aux_rd_interval(link, lt_settings, DPRX);
|
||||
|
||||
@ -720,11 +727,12 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
dp_wait_for_training_aux_rd_interval(link, wait_time_microsec);
|
||||
|
||||
/* Read status and adjustment requests from DPCD. */
|
||||
status = dp_get_lane_status_and_drive_settings(link,
|
||||
status = dp_get_lane_status_and_lane_adjust(
|
||||
link,
|
||||
lt_settings,
|
||||
dpcd_lane_status,
|
||||
&dpcd_lane_status_updated,
|
||||
&req_settings,
|
||||
dpcd_lane_adjust,
|
||||
DPRX);
|
||||
if (status != DC_OK) {
|
||||
result = LINK_TRAINING_ABORT;
|
||||
@ -745,7 +753,8 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li
|
||||
}
|
||||
|
||||
/* Update VS/PE. */
|
||||
dp_update_drive_settings(lt_settings, req_settings);
|
||||
dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
|
||||
lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
|
||||
}
|
||||
|
||||
/* Abort link training if equalization failed due to HPD unplug. */
|
||||
|
@ -1155,9 +1155,17 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
|
||||
pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
|
||||
}
|
||||
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
res = false;
|
||||
if (!pipe_ctx->stream->ctx->dc->config.enable_windowed_mpo_odm) {
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
|
||||
pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
res = false;
|
||||
} else {
|
||||
/* Clamp minimum viewport size */
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE)
|
||||
pipe_ctx->plane_res.scl_data.viewport.height = MIN_VIEWPORT_SIZE;
|
||||
if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
|
||||
pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE;
|
||||
}
|
||||
|
||||
DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n"
|
||||
"src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n",
|
||||
|
@ -47,7 +47,7 @@ struct aux_payload;
|
||||
struct set_config_cmd_payload;
|
||||
struct dmub_notification;
|
||||
|
||||
#define DC_VER "3.2.157"
|
||||
#define DC_VER "3.2.159"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
@ -211,12 +211,12 @@ struct dc_dcc_setting {
|
||||
unsigned int max_uncompressed_blk_size;
|
||||
bool independent_64b_blks;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
//These bitfields to be used starting with DCN 3.0
|
||||
//These bitfields to be used starting with DCN
|
||||
struct {
|
||||
uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN 3.0 (the worst compression case)
|
||||
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0
|
||||
uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0
|
||||
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case)
|
||||
uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN (the worst compression case)
|
||||
uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN
|
||||
uint32_t dcc_256_128_128 : 1; //available starting with DCN
|
||||
uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN (the best compression case)
|
||||
} dcc_controls;
|
||||
#endif
|
||||
};
|
||||
@ -323,6 +323,7 @@ struct dc_config {
|
||||
bool multi_mon_pp_mclk_switch;
|
||||
bool disable_dmcu;
|
||||
bool enable_4to1MPC;
|
||||
bool enable_windowed_mpo_odm;
|
||||
bool allow_edp_hotplug_detection;
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool clamp_min_dcfclk;
|
||||
@ -342,6 +343,12 @@ enum visual_confirm {
|
||||
VISUAL_CONFIRM_SWIZZLE = 9,
|
||||
};
|
||||
|
||||
enum dc_psr_power_opts {
|
||||
psr_power_opt_invalid = 0x0,
|
||||
psr_power_opt_smu_opt_static_screen = 0x1,
|
||||
psr_power_opt_z10_static_screen = 0x10,
|
||||
};
|
||||
|
||||
enum dcc_option {
|
||||
DCC_ENABLE = 0,
|
||||
DCC_DISABLE = 1,
|
||||
@ -725,6 +732,9 @@ struct dc {
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool idle_optimizations_allowed;
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
bool enable_c20_dtm_b0;
|
||||
#endif
|
||||
|
||||
/* Require to maintain clocks and bandwidth for UEFI enabled HW */
|
||||
|
||||
@ -931,6 +941,7 @@ union surface_update_flags {
|
||||
uint32_t bandwidth_change:1;
|
||||
uint32_t clock_change:1;
|
||||
uint32_t stereo_format_change:1;
|
||||
uint32_t lut_3d:1;
|
||||
uint32_t full_update:1;
|
||||
} bits;
|
||||
|
||||
@ -1417,6 +1428,12 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
|
||||
uint32_t link_index,
|
||||
struct set_config_cmd_payload *payload,
|
||||
struct dmub_notification *notify);
|
||||
|
||||
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint8_t mst_alloc_slots,
|
||||
uint8_t *mst_slots_in_use);
|
||||
|
||||
/*******************************************************************************
|
||||
* DSC Interfaces
|
||||
******************************************************************************/
|
||||
|
@ -174,11 +174,6 @@ struct dc_lane_settings {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dc_link_training_settings {
|
||||
struct dc_link_settings link;
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
|
||||
};
|
||||
|
||||
struct dc_link_training_overrides {
|
||||
enum dc_voltage_swing *voltage_swing;
|
||||
enum dc_pre_emphasis *pre_emphasis;
|
||||
|
@ -85,6 +85,7 @@ struct psr_settings {
|
||||
*/
|
||||
bool psr_frame_capture_indication_req;
|
||||
unsigned int psr_sdp_transmit_line_num_deadline;
|
||||
unsigned int psr_power_opt;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -123,6 +124,10 @@ struct dc_link {
|
||||
struct dc_link_settings cur_link_settings;
|
||||
struct dc_lane_settings cur_lane_setting[LANE_COUNT_DP_MAX];
|
||||
struct dc_link_settings preferred_link_setting;
|
||||
/* preferred_training_settings are override values that
|
||||
* come from DM. DM is responsible for the memory
|
||||
* management of the override pointers.
|
||||
*/
|
||||
struct dc_link_training_overrides preferred_training_settings;
|
||||
struct dp_audio_test_data audio_test_data;
|
||||
|
||||
@ -177,11 +182,15 @@ struct dc_link {
|
||||
|
||||
struct psr_settings psr_settings;
|
||||
|
||||
/* Drive settings read from integrated info table */
|
||||
struct dc_lane_settings bios_forced_drive_settings;
|
||||
|
||||
/* MST record stream using this link */
|
||||
struct link_flags {
|
||||
bool dp_keep_receiver_powered;
|
||||
bool dp_skip_DID2;
|
||||
bool dp_skip_reset_segment;
|
||||
bool dp_mot_reset_segment;
|
||||
} wa_flags;
|
||||
struct link_mst_stream_allocation_table mst_stream_alloc_table;
|
||||
|
||||
@ -267,8 +276,8 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link);
|
||||
|
||||
int dc_link_get_target_backlight_pwm(const struct dc_link *link);
|
||||
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable,
|
||||
bool wait, bool force_static);
|
||||
bool dc_link_set_psr_allow_active(struct dc_link *dc_link, const bool *enable,
|
||||
bool wait, bool force_static, const unsigned int *power_opts);
|
||||
|
||||
bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state);
|
||||
|
||||
|
@ -514,13 +514,15 @@ void dce_aud_az_configure(
|
||||
union audio_sample_rates sample_rates =
|
||||
audio_mode->sample_rates;
|
||||
uint8_t byte2 = audio_mode->max_bit_rate;
|
||||
uint8_t channel_count = audio_mode->channel_count;
|
||||
|
||||
/* adjust specific properties */
|
||||
switch (audio_format_code) {
|
||||
case AUDIO_FORMAT_CODE_LINEARPCM: {
|
||||
|
||||
check_audio_bandwidth(
|
||||
crtc_info,
|
||||
audio_mode->channel_count,
|
||||
channel_count,
|
||||
signal,
|
||||
&sample_rates);
|
||||
|
||||
@ -548,7 +550,7 @@ void dce_aud_az_configure(
|
||||
|
||||
/* fill audio format data */
|
||||
set_reg_field_value(value,
|
||||
audio_mode->channel_count - 1,
|
||||
channel_count - 1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
MAX_CHANNELS);
|
||||
|
||||
|
@ -534,17 +534,26 @@ struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine
|
||||
static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
|
||||
{
|
||||
if (payload->i2c_over_aux) {
|
||||
if (payload->write_status_update) {
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT;
|
||||
else
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
|
||||
}
|
||||
if (payload->write) {
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
|
||||
else
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
|
||||
}
|
||||
if (payload->mot)
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
|
||||
|
||||
return I2CAUX_TRANSACTION_ACTION_I2C_READ;
|
||||
}
|
||||
if (payload->write)
|
||||
return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
|
||||
|
||||
return I2CAUX_TRANSACTION_ACTION_DP_READ;
|
||||
}
|
||||
|
||||
@ -698,7 +707,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
||||
aux_defer_retries = 0,
|
||||
aux_i2c_defer_retries = 0,
|
||||
aux_timeout_retries = 0,
|
||||
aux_invalid_reply_retries = 0;
|
||||
aux_invalid_reply_retries = 0,
|
||||
aux_ack_m_retries = 0;
|
||||
|
||||
if (ddc_pin) {
|
||||
aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
|
||||
@ -758,9 +768,27 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
|
||||
aux_defer_retries,
|
||||
AUX_MAX_RETRIES);
|
||||
goto fail;
|
||||
} else {
|
||||
} else
|
||||
udelay(300);
|
||||
} else if (payload->write && ret > 0) {
|
||||
/* sink requested more time to complete the write via AUX_ACKM */
|
||||
if (++aux_ack_m_retries >= AUX_MAX_RETRIES) {
|
||||
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
|
||||
LOG_FLAG_Error_I2cAux,
|
||||
"dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d",
|
||||
aux_ack_m_retries,
|
||||
AUX_MAX_RETRIES);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* retry reading the write status until complete
|
||||
* NOTE: payload is modified here
|
||||
*/
|
||||
payload->write = false;
|
||||
payload->write_status_update = true;
|
||||
payload->length = 0;
|
||||
udelay(300);
|
||||
|
||||
} else
|
||||
return true;
|
||||
break;
|
||||
|
@ -1151,7 +1151,8 @@ struct dce_hwseq_registers {
|
||||
type DOMAIN_POWER_GATE;\
|
||||
type DOMAIN_PGFSM_PWR_STATUS;\
|
||||
type HPO_HDMISTREAMCLK_G_GATE_DIS;\
|
||||
type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;
|
||||
type DISABLE_HOSTVM_FORCE_ALLOW_PSTATE;\
|
||||
type I2C_LIGHT_SLEEP_FORCE;
|
||||
|
||||
struct dce_hwseq_shift {
|
||||
HWSEQ_REG_FIELD_LIST(uint8_t)
|
||||
|
@ -227,6 +227,25 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_
|
||||
dc_dmub_srv_wait_idle(dc->dmub_srv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PSR power optimization flags.
|
||||
*/
|
||||
static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *dc = dmub->ctx;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.psr_set_power_opt.header.type = DMUB_CMD__PSR;
|
||||
cmd.psr_set_power_opt.header.sub_type = DMUB_CMD__SET_PSR_POWER_OPT;
|
||||
cmd.psr_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_power_opt_data);
|
||||
cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt;
|
||||
|
||||
dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
|
||||
dc_dmub_srv_cmd_execute(dc->dmub_srv);
|
||||
dc_dmub_srv_wait_idle(dc->dmub_srv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup PSR by programming phy registers and sending psr hw context values to firmware.
|
||||
*/
|
||||
@ -358,6 +377,7 @@ static const struct dmub_psr_funcs psr_funcs = {
|
||||
.psr_set_level = dmub_psr_set_level,
|
||||
.psr_force_static = dmub_psr_force_static,
|
||||
.psr_get_residency = dmub_psr_get_residency,
|
||||
.psr_set_power_opt = dmub_psr_set_power_opt,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -46,6 +46,7 @@ struct dmub_psr_funcs {
|
||||
void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst);
|
||||
void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency,
|
||||
uint8_t panel_inst);
|
||||
void (*psr_set_power_opt)(struct dmub_psr *dmub, unsigned int power_opt);
|
||||
};
|
||||
|
||||
struct dmub_psr *dmub_psr_create(struct dc_context *ctx);
|
||||
|
@ -205,9 +205,17 @@ static void dpp1_power_on_dscl(
|
||||
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
|
||||
|
||||
if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) {
|
||||
REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, power_on ? 0 : 3);
|
||||
if (power_on)
|
||||
if (power_on) {
|
||||
REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0);
|
||||
REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5);
|
||||
} else {
|
||||
if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) {
|
||||
dpp->base.ctx->dc->optimized_required = true;
|
||||
dpp->base.deferred_reg_writes.bits.disable_dscl = true;
|
||||
} else {
|
||||
REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1378,6 +1378,12 @@ void dcn10_init_hw(struct dc *dc)
|
||||
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
|
||||
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
|
||||
|
||||
/* Align bw context with hw config when system resume. */
|
||||
if (dc->clk_mgr->clks.dispclk_khz != 0 && dc->clk_mgr->clks.dppclk_khz != 0) {
|
||||
dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz = dc->clk_mgr->clks.dispclk_khz;
|
||||
dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz = dc->clk_mgr->clks.dppclk_khz;
|
||||
}
|
||||
|
||||
// Initialize the dccg
|
||||
if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
|
||||
dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
|
||||
|
@ -3660,9 +3660,6 @@ static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
|
||||
return DML_PROJECT_NAVI10v2;
|
||||
}
|
||||
|
||||
#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
|
||||
#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
|
||||
|
||||
static bool init_soc_bounding_box(struct dc *dc,
|
||||
struct dcn20_resource_pool *pool)
|
||||
{
|
||||
@ -3698,16 +3695,22 @@ static bool init_soc_bounding_box(struct dc *dc,
|
||||
clock_limits_available = (status == PP_SMU_RESULT_OK);
|
||||
}
|
||||
|
||||
if (clock_limits_available && uclk_states_available && num_states)
|
||||
if (clock_limits_available && uclk_states_available && num_states) {
|
||||
DC_FP_START();
|
||||
dcn20_update_bounding_box(dc, loaded_bb, &max_clocks, uclk_states, num_states);
|
||||
else if (clock_limits_available)
|
||||
DC_FP_END();
|
||||
} else if (clock_limits_available) {
|
||||
DC_FP_START();
|
||||
dcn20_cap_soc_clocks(loaded_bb, max_clocks);
|
||||
DC_FP_END();
|
||||
}
|
||||
}
|
||||
|
||||
loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
loaded_ip->max_num_dpp = pool->base.pipe_count;
|
||||
DC_FP_START();
|
||||
dcn20_patch_bounding_box(dc, loaded_bb);
|
||||
|
||||
DC_FP_END();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3727,8 +3730,6 @@ static bool dcn20_resource_construct(
|
||||
enum dml_project dml_project_version =
|
||||
get_dml_project_version(ctx->asic_id.hw_internal_rev);
|
||||
|
||||
DC_FP_START();
|
||||
|
||||
ctx->dc_bios->regs = &bios_regs;
|
||||
pool->base.funcs = &dcn20_res_pool_funcs;
|
||||
|
||||
@ -4077,12 +4078,10 @@ static bool dcn20_resource_construct(
|
||||
pool->base.oem_device = NULL;
|
||||
}
|
||||
|
||||
DC_FP_END();
|
||||
return true;
|
||||
|
||||
create_fail:
|
||||
|
||||
DC_FP_END();
|
||||
dcn20_resource_destruct(pool);
|
||||
|
||||
return false;
|
||||
|
@ -494,6 +494,20 @@ void dpp3_deferred_update(
|
||||
int bypass_state;
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_dscl) {
|
||||
REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3);
|
||||
dpp_base->deferred_reg_writes.bits.disable_dscl = false;
|
||||
}
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_gamcor) {
|
||||
REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &bypass_state);
|
||||
if (bypass_state == 0) { // only program if bypass was latched
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 3);
|
||||
} else
|
||||
ASSERT(0); // LUT select was updated again before vupdate
|
||||
dpp_base->deferred_reg_writes.bits.disable_gamcor = false;
|
||||
}
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_blnd_lut) {
|
||||
REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &bypass_state);
|
||||
if (bypass_state == 0) { // only program if bypass was latched
|
||||
|
@ -136,9 +136,13 @@ static void dpp3_power_on_gamcor_lut(
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, power_on ? 0 : 3);
|
||||
if (power_on)
|
||||
if (power_on) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0);
|
||||
REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5);
|
||||
} else {
|
||||
dpp_base->ctx->dc->optimized_required = true;
|
||||
dpp_base->deferred_reg_writes.bits.disable_gamcor = true;
|
||||
}
|
||||
} else
|
||||
REG_SET(CM_MEM_PWR_CTRL, 0,
|
||||
GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1);
|
||||
|
@ -1707,9 +1707,6 @@ bool dcn30_release_post_bldn_3dlut(
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
|
||||
#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
|
||||
|
||||
static bool is_soc_bounding_box_valid(struct dc *dc)
|
||||
{
|
||||
uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
|
||||
@ -1929,23 +1926,25 @@ noinline bool dcn30_internal_validate_bw(
|
||||
if (vlevel == context->bw_ctx.dml.soc.num_states)
|
||||
goto validate_fail;
|
||||
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;
|
||||
if (!dc->config.enable_windowed_mpo_odm) {
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *mpo_pipe = pipe->bottom_pipe;
|
||||
|
||||
if (!pipe->stream)
|
||||
continue;
|
||||
if (!pipe->stream)
|
||||
continue;
|
||||
|
||||
/* We only support full screen mpo with ODM */
|
||||
if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled
|
||||
&& pipe->plane_state && mpo_pipe
|
||||
&& memcmp(&mpo_pipe->plane_res.scl_data.recout,
|
||||
&pipe->plane_res.scl_data.recout,
|
||||
sizeof(struct rect)) != 0) {
|
||||
ASSERT(mpo_pipe->plane_state != pipe->plane_state);
|
||||
goto validate_fail;
|
||||
/* We only support full screen mpo with ODM */
|
||||
if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled
|
||||
&& pipe->plane_state && mpo_pipe
|
||||
&& memcmp(&mpo_pipe->plane_res.scl_data.recout,
|
||||
&pipe->plane_res.scl_data.recout,
|
||||
sizeof(struct rect)) != 0) {
|
||||
ASSERT(mpo_pipe->plane_state != pipe->plane_state);
|
||||
goto validate_fail;
|
||||
}
|
||||
pipe_idx++;
|
||||
}
|
||||
pipe_idx++;
|
||||
}
|
||||
|
||||
/* merge pipes if necessary */
|
||||
@ -2323,7 +2322,9 @@ bool dcn30_validate_bandwidth(struct dc *dc,
|
||||
goto validate_out;
|
||||
}
|
||||
|
||||
DC_FP_START();
|
||||
dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
|
||||
DC_FP_END();
|
||||
|
||||
BW_VAL_TRACE_END_WATERMARKS();
|
||||
|
||||
|
@ -13,32 +13,6 @@
|
||||
DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
|
||||
dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
|
||||
|
||||
ifdef CONFIG_X86
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -mhard-float -maltivec
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_IS_GCC
|
||||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -mhard-float
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
ifdef IS_OLD_GCC
|
||||
# Stack alignment mismatch, proceed with caution.
|
||||
# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
|
||||
# (8B stack alignment).
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -mpreferred-stack-boundary=4
|
||||
else
|
||||
CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -msse2
|
||||
endif
|
||||
endif
|
||||
|
||||
AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DCN301)
|
||||
|
@ -82,6 +82,7 @@
|
||||
#include "dce/dce_i2c.h"
|
||||
|
||||
#include "dml/dcn30/display_mode_vba_30.h"
|
||||
#include "dml/dcn301/dcn301_fpu.h"
|
||||
#include "vm_helper.h"
|
||||
#include "dcn20/dcn20_vmid.h"
|
||||
#include "amdgpu_socbb.h"
|
||||
@ -91,184 +92,6 @@
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
struct _vcs_dpi_ip_params_st dcn3_01_ip = {
|
||||
.odm_capable = 1,
|
||||
.gpuvm_enable = 1,
|
||||
.hostvm_enable = 1,
|
||||
.gpuvm_max_page_table_levels = 1,
|
||||
.hostvm_max_page_table_levels = 2,
|
||||
.hostvm_cached_page_table_levels = 0,
|
||||
.pte_group_size_bytes = 2048,
|
||||
.num_dsc = 3,
|
||||
.rob_buffer_size_kbytes = 184,
|
||||
.det_buffer_size_kbytes = 184,
|
||||
.dpte_buffer_size_in_pte_reqs_luma = 64,
|
||||
.dpte_buffer_size_in_pte_reqs_chroma = 32,
|
||||
.pde_proc_buffer_size_64k_reqs = 48,
|
||||
.dpp_output_buffer_pixels = 2560,
|
||||
.opp_output_buffer_lines = 1,
|
||||
.pixel_chunk_size_kbytes = 8,
|
||||
.meta_chunk_size_kbytes = 2,
|
||||
.writeback_chunk_size_kbytes = 8,
|
||||
.line_buffer_size_bits = 789504,
|
||||
.is_line_buffer_bpp_fixed = 0, // ?
|
||||
.line_buffer_fixed_bpp = 48, // ?
|
||||
.dcc_supported = true,
|
||||
.writeback_interface_buffer_size_kbytes = 90,
|
||||
.writeback_line_buffer_buffer_size = 656640,
|
||||
.max_line_buffer_lines = 12,
|
||||
.writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640
|
||||
.writeback_chroma_buffer_size_kbytes = 8,
|
||||
.writeback_chroma_line_buffer_width_pixels = 4,
|
||||
.writeback_max_hscl_ratio = 1,
|
||||
.writeback_max_vscl_ratio = 1,
|
||||
.writeback_min_hscl_ratio = 1,
|
||||
.writeback_min_vscl_ratio = 1,
|
||||
.writeback_max_hscl_taps = 1,
|
||||
.writeback_max_vscl_taps = 1,
|
||||
.writeback_line_buffer_luma_buffer_size = 0,
|
||||
.writeback_line_buffer_chroma_buffer_size = 14643,
|
||||
.cursor_buffer_size = 8,
|
||||
.cursor_chunk_size = 2,
|
||||
.max_num_otg = 4,
|
||||
.max_num_dpp = 4,
|
||||
.max_num_wb = 1,
|
||||
.max_dchub_pscl_bw_pix_per_clk = 4,
|
||||
.max_pscl_lb_bw_pix_per_clk = 2,
|
||||
.max_lb_vscl_bw_pix_per_clk = 4,
|
||||
.max_vscl_hscl_bw_pix_per_clk = 4,
|
||||
.max_hscl_ratio = 6,
|
||||
.max_vscl_ratio = 6,
|
||||
.hscl_mults = 4,
|
||||
.vscl_mults = 4,
|
||||
.max_hscl_taps = 8,
|
||||
.max_vscl_taps = 8,
|
||||
.dispclk_ramp_margin_percent = 1,
|
||||
.underscan_factor = 1.11,
|
||||
.min_vblank_lines = 32,
|
||||
.dppclk_delay_subtotal = 46,
|
||||
.dynamic_metadata_vm_enabled = true,
|
||||
.dppclk_delay_scl_lb_only = 16,
|
||||
.dppclk_delay_scl = 50,
|
||||
.dppclk_delay_cnvc_formatter = 27,
|
||||
.dppclk_delay_cnvc_cursor = 6,
|
||||
.dispclk_delay_subtotal = 119,
|
||||
.dcfclk_cstate_latency = 5.2, // SRExitTime
|
||||
.max_inter_dcn_tile_repeaters = 8,
|
||||
.max_num_hdmi_frl_outputs = 0,
|
||||
.odm_combine_4to1_supported = true,
|
||||
|
||||
.xfc_supported = false,
|
||||
.xfc_fill_bw_overhead_percent = 10.0,
|
||||
.xfc_fill_constant_bytes = 0,
|
||||
.gfx7_compat_tiling_supported = 0,
|
||||
.number_of_cursors = 1,
|
||||
};
|
||||
|
||||
struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
|
||||
.clock_limits = {
|
||||
{
|
||||
.state = 0,
|
||||
.dram_speed_mts = 2400.0,
|
||||
.fabricclk_mhz = 600,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 400.0,
|
||||
.dscclk_mhz = 206.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 600.0,
|
||||
},
|
||||
{
|
||||
.state = 1,
|
||||
.dram_speed_mts = 2400.0,
|
||||
.fabricclk_mhz = 688,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 400.0,
|
||||
.dscclk_mhz = 206.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 600.0,
|
||||
},
|
||||
{
|
||||
.state = 2,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 608.0,
|
||||
.dscclk_mhz = 296.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 3,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 715.0,
|
||||
.dcfclk_mhz = 676.0,
|
||||
.dscclk_mhz = 338.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 4,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 953.0,
|
||||
.dcfclk_mhz = 810.0,
|
||||
.dscclk_mhz = 338.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
},
|
||||
|
||||
.sr_exit_time_us = 9.0,
|
||||
.sr_enter_plus_exit_time_us = 11.0,
|
||||
.urgent_latency_us = 4.0,
|
||||
.urgent_latency_pixel_data_only_us = 4.0,
|
||||
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
|
||||
.urgent_latency_vm_data_only_us = 4.0,
|
||||
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
|
||||
.max_avg_sdp_bw_use_normal_percent = 60.0,
|
||||
.max_avg_dram_bw_use_normal_percent = 60.0,
|
||||
.writeback_latency_us = 12.0,
|
||||
.max_request_size_bytes = 256,
|
||||
.dram_channel_width_bytes = 4,
|
||||
.fabric_datapath_to_dcn_data_return_bytes = 32,
|
||||
.dcn_downspread_percent = 0.5,
|
||||
.downspread_percent = 0.38,
|
||||
.dram_page_open_time_ns = 50.0,
|
||||
.dram_rw_turnaround_time_ns = 17.5,
|
||||
.dram_return_buffer_per_channel_bytes = 8192,
|
||||
.round_trip_ping_latency_dcfclk_cycles = 191,
|
||||
.urgent_out_of_order_return_per_channel_bytes = 4096,
|
||||
.channel_interleave_bytes = 256,
|
||||
.num_banks = 8,
|
||||
.num_chans = 4,
|
||||
.gpuvm_min_page_size_bytes = 4096,
|
||||
.hostvm_min_page_size_bytes = 4096,
|
||||
.dram_clock_change_latency_us = 23.84,
|
||||
.writeback_dram_clock_change_latency_us = 23.0,
|
||||
.return_bus_width_bytes = 64,
|
||||
.dispclk_dppclk_vco_speed_mhz = 3550,
|
||||
.xfc_bus_transport_time_us = 20, // ?
|
||||
.xfc_xbuf_latency_tolerance_us = 4, // ?
|
||||
.use_urgent_burst_bw = 1, // ?
|
||||
.num_states = 5,
|
||||
.do_urgent_latency_adjustment = false,
|
||||
.urgent_latency_adjustment_fabric_clock_component_us = 0,
|
||||
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
|
||||
};
|
||||
|
||||
enum dcn301_clk_src_array_id {
|
||||
DCN301_CLK_SRC_PLL0,
|
||||
DCN301_CLK_SRC_PLL1,
|
||||
@ -1480,8 +1303,6 @@ static struct dc_cap_funcs cap_funcs = {
|
||||
.get_dcc_compression_cap = dcn20_get_dcc_compression_cap
|
||||
};
|
||||
|
||||
#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
|
||||
#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
|
||||
|
||||
static bool is_soc_bounding_box_valid(struct dc *dc)
|
||||
{
|
||||
@ -1508,26 +1329,24 @@ static bool init_soc_bounding_box(struct dc *dc,
|
||||
|
||||
loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
loaded_ip->max_num_dpp = pool->base.pipe_count;
|
||||
DC_FP_START();
|
||||
dcn20_patch_bounding_box(dc, loaded_bb);
|
||||
DC_FP_END();
|
||||
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
|
||||
struct bp_soc_bb_info bb_info = {0};
|
||||
|
||||
if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
|
||||
if (bb_info.dram_clock_change_latency_100ns > 0)
|
||||
dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
|
||||
|
||||
if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
|
||||
dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
|
||||
|
||||
if (bb_info.dram_sr_exit_latency_100ns > 0)
|
||||
dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
|
||||
DC_FP_START();
|
||||
dcn301_fpu_init_soc_bounding_box(bb_info);
|
||||
DC_FP_END();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void set_wm_ranges(
|
||||
struct pp_smu_funcs *pp_smu,
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
|
||||
@ -1550,9 +1369,9 @@ static void set_wm_ranges(
|
||||
ranges.reader_wm_sets[i].wm_inst = i;
|
||||
ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
|
||||
ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
|
||||
ranges.reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
|
||||
ranges.reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
|
||||
|
||||
DC_FP_START();
|
||||
dcn301_fpu_set_wm_ranges(i, &ranges, loaded_bb);
|
||||
DC_FP_END();
|
||||
ranges.num_reader_wm_sets = i + 1;
|
||||
}
|
||||
|
||||
@ -1572,154 +1391,6 @@ static void set_wm_ranges(
|
||||
pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges);
|
||||
}
|
||||
|
||||
static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
|
||||
{
|
||||
struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool);
|
||||
struct clk_limit_table *clk_table = &bw_params->clk_table;
|
||||
struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
|
||||
unsigned int i, closest_clk_lvl;
|
||||
int j;
|
||||
|
||||
// Default clock levels are used for diags, which may lead to overclocking.
|
||||
if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
|
||||
dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
|
||||
dcn3_01_soc.num_chans = bw_params->num_channels;
|
||||
|
||||
ASSERT(clk_table->num_entries);
|
||||
for (i = 0; i < clk_table->num_entries; i++) {
|
||||
/* loop backwards*/
|
||||
for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
|
||||
if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
|
||||
closest_clk_lvl = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clock_limits[i].state = i;
|
||||
clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
|
||||
clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
|
||||
clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
|
||||
clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
|
||||
|
||||
clock_limits[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
|
||||
clock_limits[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
|
||||
clock_limits[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
|
||||
clock_limits[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
|
||||
clock_limits[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
|
||||
clock_limits[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
|
||||
clock_limits[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
|
||||
}
|
||||
for (i = 0; i < clk_table->num_entries; i++)
|
||||
dcn3_01_soc.clock_limits[i] = clock_limits[i];
|
||||
if (clk_table->num_entries) {
|
||||
dcn3_01_soc.num_states = clk_table->num_entries;
|
||||
/* duplicate last level */
|
||||
dcn3_01_soc.clock_limits[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
|
||||
dcn3_01_soc.clock_limits[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
|
||||
}
|
||||
}
|
||||
|
||||
dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
|
||||
dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
|
||||
}
|
||||
|
||||
static void calculate_wm_set_for_vlevel(
|
||||
int vlevel,
|
||||
struct wm_range_table_entry *table_entry,
|
||||
struct dcn_watermarks *wm_set,
|
||||
struct display_mode_lib *dml,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt)
|
||||
{
|
||||
double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
|
||||
|
||||
ASSERT(vlevel < dml->soc.num_states);
|
||||
/* only pipe 0 is read for voltage and dcf/soc clocks */
|
||||
pipes[0].clks_cfg.voltage = vlevel;
|
||||
pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
|
||||
pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
|
||||
|
||||
dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
|
||||
dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
|
||||
dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
|
||||
|
||||
wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
|
||||
dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
|
||||
|
||||
}
|
||||
|
||||
static void dcn301_calculate_wm_and_dlg(
|
||||
struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
int vlevel_req)
|
||||
{
|
||||
int i, pipe_idx;
|
||||
int vlevel, vlevel_max;
|
||||
struct wm_range_table_entry *table_entry;
|
||||
struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
|
||||
|
||||
ASSERT(bw_params);
|
||||
|
||||
vlevel_max = bw_params->clk_table.num_entries - 1;
|
||||
|
||||
/* WM Set D */
|
||||
table_entry = &bw_params->wm_table.entries[WM_D];
|
||||
if (table_entry->wm_type == WM_TYPE_RETRAINING)
|
||||
vlevel = 0;
|
||||
else
|
||||
vlevel = vlevel_max;
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set C */
|
||||
table_entry = &bw_params->wm_table.entries[WM_C];
|
||||
vlevel = min(max(vlevel_req, 2), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set B */
|
||||
table_entry = &bw_params->wm_table.entries[WM_B];
|
||||
vlevel = min(max(vlevel_req, 1), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
/* WM Set A */
|
||||
table_entry = &bw_params->wm_table.entries[WM_A];
|
||||
vlevel = min(vlevel_req, vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (!context->res_ctx.pipe_ctx[i].stream)
|
||||
continue;
|
||||
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
|
||||
if (dc->config.forced_clocks) {
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
|
||||
}
|
||||
if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
|
||||
if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
|
||||
|
||||
pipe_idx++;
|
||||
}
|
||||
|
||||
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
|
||||
}
|
||||
|
||||
static struct resource_funcs dcn301_res_pool_funcs = {
|
||||
.destroy = dcn301_destroy_resource_pool,
|
||||
.link_enc_create = dcn301_link_encoder_create,
|
||||
|
@ -32,6 +32,9 @@ struct dc;
|
||||
struct resource_pool;
|
||||
struct _vcs_dpi_display_pipe_params_st;
|
||||
|
||||
extern struct _vcs_dpi_ip_params_st dcn3_01_ip;
|
||||
extern struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc;
|
||||
|
||||
struct dcn301_resource_pool {
|
||||
struct resource_pool base;
|
||||
};
|
||||
|
@ -1344,6 +1344,20 @@ void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
|
||||
dcn3_03_soc.clock_limits[i].phyclk_d18_mhz = dcn3_03_soc.clock_limits[0].phyclk_d18_mhz;
|
||||
dcn3_03_soc.clock_limits[i].dscclk_mhz = dcn3_03_soc.clock_limits[0].dscclk_mhz;
|
||||
}
|
||||
|
||||
// WA: patch strobe modes to compensate for DCN303 BW issue
|
||||
if (dcn3_03_soc.num_chans <= 4) {
|
||||
for (i = 0; i < dcn3_03_soc.num_states; i++) {
|
||||
if (dcn3_03_soc.clock_limits[i].dram_speed_mts > 1700)
|
||||
break;
|
||||
|
||||
if (dcn3_03_soc.clock_limits[i].dram_speed_mts >= 1500) {
|
||||
dcn3_03_soc.clock_limits[i].dcfclk_mhz = 100;
|
||||
dcn3_03_soc.clock_limits[i].fabricclk_mhz = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* re-init DML with updated bb */
|
||||
dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30);
|
||||
if (dc->current_state)
|
||||
|
@ -431,7 +431,7 @@ void dcn31_link_encoder_enable_dp_output(
|
||||
|
||||
if (link) {
|
||||
dpia_control.dpia_id = link->ddc_hw_inst;
|
||||
dpia_control.fec_rdy = link->fec_state == dc_link_fec_ready ? 1 : 0;
|
||||
dpia_control.fec_rdy = dc_link_should_enable_fec(link);
|
||||
} else {
|
||||
DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__);
|
||||
BREAK_TO_DEBUGGER();
|
||||
@ -476,7 +476,7 @@ void dcn31_link_encoder_enable_dp_mst_output(
|
||||
|
||||
if (link) {
|
||||
dpia_control.dpia_id = link->ddc_hw_inst;
|
||||
dpia_control.fec_rdy = link->fec_state == dc_link_fec_ready ? 1 : 0;
|
||||
dpia_control.fec_rdy = dc_link_should_enable_fec(link);
|
||||
} else {
|
||||
DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__);
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "dcn10/dcn10_hw_sequencer.h"
|
||||
#include "inc/link_enc_cfg.h"
|
||||
#include "dcn30/dcn30_vpg.h"
|
||||
#include "dce/dce_i2c_hw.h"
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
@ -259,6 +260,10 @@ void dcn31_init_hw(struct dc *dc)
|
||||
/* power AFMT HDMI memory TODO: may move to dis/en output save power*/
|
||||
REG_WRITE(DIO_MEM_PWR_CTRL, 0);
|
||||
|
||||
// Set i2c to light sleep until engine is setup
|
||||
if (dc->debug.enable_mem_low_power.bits.i2c)
|
||||
REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
|
||||
|
||||
if (!dc->debug.disable_clock_gate) {
|
||||
/* enable all DCN clock gating */
|
||||
REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
|
||||
|
@ -101,8 +101,6 @@
|
||||
#include "link_enc_cfg.h"
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
|
||||
#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
|
||||
|
||||
#define DCN3_1_DEFAULT_DET_SIZE 384
|
||||
|
||||
@ -899,7 +897,8 @@ static const struct dce_hwseq_registers hwseq_reg = {
|
||||
HWS_SF(, DMU_MEM_PWR_CNTL, DMCU_ERAM_MEM_PWR_FORCE, mask_sh), \
|
||||
HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
|
||||
HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
|
||||
HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh)
|
||||
HWS_SF(, MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, mask_sh), \
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dce_hwseq_shift hwseq_shift = {
|
||||
HWSEQ_DCN31_MASK_SH_LIST(__SHIFT)
|
||||
@ -1833,7 +1832,7 @@ static int dcn31_populate_dml_pipes_from_context(
|
||||
return pipe_cnt;
|
||||
}
|
||||
|
||||
static void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)
|
||||
void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
if (dc->clk_mgr->bw_params->wm_table.entries[WM_A].valid) {
|
||||
context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.entries[WM_A].pstate_latency_us;
|
||||
@ -1977,7 +1976,7 @@ static void dcn31_calculate_wm_and_dlg_fp(
|
||||
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
|
||||
}
|
||||
|
||||
static void dcn31_calculate_wm_and_dlg(
|
||||
void dcn31_calculate_wm_and_dlg(
|
||||
struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
@ -2459,6 +2458,8 @@ static bool dcn31_resource_construct(
|
||||
|
||||
dc->cap_funcs = cap_funcs;
|
||||
|
||||
dc->dcn_ip->max_num_dpp = dcn3_1_ip.max_num_dpp;
|
||||
|
||||
DC_FP_END();
|
||||
|
||||
return true;
|
||||
|
@ -35,6 +35,16 @@ struct dcn31_resource_pool {
|
||||
struct resource_pool base;
|
||||
};
|
||||
|
||||
bool dcn31_validate_bandwidth(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
bool fast_validate);
|
||||
void dcn31_calculate_wm_and_dlg(
|
||||
struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
int vlevel);
|
||||
void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context);
|
||||
|
||||
struct resource_pool *dcn31_create_resource_pool(
|
||||
const struct dc_init_data *init_data,
|
||||
struct dc *dc);
|
||||
|
@ -35,6 +35,8 @@ struct cp_psp_stream_config {
|
||||
uint8_t link_enc_idx;
|
||||
uint8_t stream_enc_idx;
|
||||
uint8_t phy_idx;
|
||||
uint8_t dio_output_idx;
|
||||
uint8_t dio_output_type;
|
||||
uint8_t assr_enabled;
|
||||
uint8_t mst_enabled;
|
||||
uint8_t dp2_enabled;
|
||||
|
@ -70,6 +70,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.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)
|
||||
@ -83,7 +85,9 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags)
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags)
|
||||
@ -99,6 +103,8 @@ 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
|
||||
DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
|
||||
DML += dcn301/dcn301_fpu.o
|
||||
DML += dsc/rc_calc_fpu.o
|
||||
endif
|
||||
|
||||
AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML))
|
||||
|
390
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
Normal file
390
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
Normal file
@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright 2019-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 "clk_mgr.h"
|
||||
#include "dcn20/dcn20_resource.h"
|
||||
#include "dcn301/dcn301_resource.h"
|
||||
|
||||
#include "dml/dcn20/dcn20_fpu.h"
|
||||
#include "dcn301_fpu.h"
|
||||
|
||||
#define TO_DCN301_RES_POOL(pool)\
|
||||
container_of(pool, struct dcn301_resource_pool, base)
|
||||
|
||||
/* Based on: //vidip/dc/dcn3/doc/architecture/DCN3x_Display_Mode.xlsm#83 */
|
||||
struct _vcs_dpi_ip_params_st dcn3_01_ip = {
|
||||
.odm_capable = 1,
|
||||
.gpuvm_enable = 1,
|
||||
.hostvm_enable = 1,
|
||||
.gpuvm_max_page_table_levels = 1,
|
||||
.hostvm_max_page_table_levels = 2,
|
||||
.hostvm_cached_page_table_levels = 0,
|
||||
.pte_group_size_bytes = 2048,
|
||||
.num_dsc = 3,
|
||||
.rob_buffer_size_kbytes = 184,
|
||||
.det_buffer_size_kbytes = 184,
|
||||
.dpte_buffer_size_in_pte_reqs_luma = 64,
|
||||
.dpte_buffer_size_in_pte_reqs_chroma = 32,
|
||||
.pde_proc_buffer_size_64k_reqs = 48,
|
||||
.dpp_output_buffer_pixels = 2560,
|
||||
.opp_output_buffer_lines = 1,
|
||||
.pixel_chunk_size_kbytes = 8,
|
||||
.meta_chunk_size_kbytes = 2,
|
||||
.writeback_chunk_size_kbytes = 8,
|
||||
.line_buffer_size_bits = 789504,
|
||||
.is_line_buffer_bpp_fixed = 0, // ?
|
||||
.line_buffer_fixed_bpp = 48, // ?
|
||||
.dcc_supported = true,
|
||||
.writeback_interface_buffer_size_kbytes = 90,
|
||||
.writeback_line_buffer_buffer_size = 656640,
|
||||
.max_line_buffer_lines = 12,
|
||||
.writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640
|
||||
.writeback_chroma_buffer_size_kbytes = 8,
|
||||
.writeback_chroma_line_buffer_width_pixels = 4,
|
||||
.writeback_max_hscl_ratio = 1,
|
||||
.writeback_max_vscl_ratio = 1,
|
||||
.writeback_min_hscl_ratio = 1,
|
||||
.writeback_min_vscl_ratio = 1,
|
||||
.writeback_max_hscl_taps = 1,
|
||||
.writeback_max_vscl_taps = 1,
|
||||
.writeback_line_buffer_luma_buffer_size = 0,
|
||||
.writeback_line_buffer_chroma_buffer_size = 14643,
|
||||
.cursor_buffer_size = 8,
|
||||
.cursor_chunk_size = 2,
|
||||
.max_num_otg = 4,
|
||||
.max_num_dpp = 4,
|
||||
.max_num_wb = 1,
|
||||
.max_dchub_pscl_bw_pix_per_clk = 4,
|
||||
.max_pscl_lb_bw_pix_per_clk = 2,
|
||||
.max_lb_vscl_bw_pix_per_clk = 4,
|
||||
.max_vscl_hscl_bw_pix_per_clk = 4,
|
||||
.max_hscl_ratio = 6,
|
||||
.max_vscl_ratio = 6,
|
||||
.hscl_mults = 4,
|
||||
.vscl_mults = 4,
|
||||
.max_hscl_taps = 8,
|
||||
.max_vscl_taps = 8,
|
||||
.dispclk_ramp_margin_percent = 1,
|
||||
.underscan_factor = 1.11,
|
||||
.min_vblank_lines = 32,
|
||||
.dppclk_delay_subtotal = 46,
|
||||
.dynamic_metadata_vm_enabled = true,
|
||||
.dppclk_delay_scl_lb_only = 16,
|
||||
.dppclk_delay_scl = 50,
|
||||
.dppclk_delay_cnvc_formatter = 27,
|
||||
.dppclk_delay_cnvc_cursor = 6,
|
||||
.dispclk_delay_subtotal = 119,
|
||||
.dcfclk_cstate_latency = 5.2, // SRExitTime
|
||||
.max_inter_dcn_tile_repeaters = 8,
|
||||
.max_num_hdmi_frl_outputs = 0,
|
||||
.odm_combine_4to1_supported = true,
|
||||
|
||||
.xfc_supported = false,
|
||||
.xfc_fill_bw_overhead_percent = 10.0,
|
||||
.xfc_fill_constant_bytes = 0,
|
||||
.gfx7_compat_tiling_supported = 0,
|
||||
.number_of_cursors = 1,
|
||||
};
|
||||
|
||||
struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
|
||||
.clock_limits = {
|
||||
{
|
||||
.state = 0,
|
||||
.dram_speed_mts = 2400.0,
|
||||
.fabricclk_mhz = 600,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 400.0,
|
||||
.dscclk_mhz = 206.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 600.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 1,
|
||||
.dram_speed_mts = 2400.0,
|
||||
.fabricclk_mhz = 688,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 400.0,
|
||||
.dscclk_mhz = 206.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 600.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 2,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 278.0,
|
||||
.dcfclk_mhz = 608.0,
|
||||
.dscclk_mhz = 296.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 3,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 715.0,
|
||||
.dcfclk_mhz = 676.0,
|
||||
.dscclk_mhz = 338.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
|
||||
{
|
||||
.state = 4,
|
||||
.dram_speed_mts = 4267.0,
|
||||
.fabricclk_mhz = 1067,
|
||||
.socclk_mhz = 953.0,
|
||||
.dcfclk_mhz = 810.0,
|
||||
.dscclk_mhz = 338.0,
|
||||
.dppclk_mhz = 1015.0,
|
||||
.dispclk_mhz = 1015.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
},
|
||||
},
|
||||
|
||||
.sr_exit_time_us = 9.0,
|
||||
.sr_enter_plus_exit_time_us = 11.0,
|
||||
.urgent_latency_us = 4.0,
|
||||
.urgent_latency_pixel_data_only_us = 4.0,
|
||||
.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
|
||||
.urgent_latency_vm_data_only_us = 4.0,
|
||||
.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
|
||||
.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
|
||||
.max_avg_sdp_bw_use_normal_percent = 60.0,
|
||||
.max_avg_dram_bw_use_normal_percent = 60.0,
|
||||
.writeback_latency_us = 12.0,
|
||||
.max_request_size_bytes = 256,
|
||||
.dram_channel_width_bytes = 4,
|
||||
.fabric_datapath_to_dcn_data_return_bytes = 32,
|
||||
.dcn_downspread_percent = 0.5,
|
||||
.downspread_percent = 0.38,
|
||||
.dram_page_open_time_ns = 50.0,
|
||||
.dram_rw_turnaround_time_ns = 17.5,
|
||||
.dram_return_buffer_per_channel_bytes = 8192,
|
||||
.round_trip_ping_latency_dcfclk_cycles = 191,
|
||||
.urgent_out_of_order_return_per_channel_bytes = 4096,
|
||||
.channel_interleave_bytes = 256,
|
||||
.num_banks = 8,
|
||||
.num_chans = 4,
|
||||
.gpuvm_min_page_size_bytes = 4096,
|
||||
.hostvm_min_page_size_bytes = 4096,
|
||||
.dram_clock_change_latency_us = 23.84,
|
||||
.writeback_dram_clock_change_latency_us = 23.0,
|
||||
.return_bus_width_bytes = 64,
|
||||
.dispclk_dppclk_vco_speed_mhz = 3550,
|
||||
.xfc_bus_transport_time_us = 20, // ?
|
||||
.xfc_xbuf_latency_tolerance_us = 4, // ?
|
||||
.use_urgent_burst_bw = 1, // ?
|
||||
.num_states = 5,
|
||||
.do_urgent_latency_adjustment = false,
|
||||
.urgent_latency_adjustment_fabric_clock_component_us = 0,
|
||||
.urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
|
||||
};
|
||||
|
||||
static void calculate_wm_set_for_vlevel(int vlevel,
|
||||
struct wm_range_table_entry *table_entry,
|
||||
struct dcn_watermarks *wm_set,
|
||||
struct display_mode_lib *dml,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt)
|
||||
{
|
||||
double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
|
||||
|
||||
ASSERT(vlevel < dml->soc.num_states);
|
||||
/* only pipe 0 is read for voltage and dcf/soc clocks */
|
||||
pipes[0].clks_cfg.voltage = vlevel;
|
||||
pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
|
||||
pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
|
||||
|
||||
dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
|
||||
dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
|
||||
dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
|
||||
|
||||
wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
|
||||
dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
|
||||
|
||||
}
|
||||
|
||||
void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
|
||||
{
|
||||
struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool);
|
||||
struct clk_limit_table *clk_table = &bw_params->clk_table;
|
||||
struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
|
||||
unsigned int i, closest_clk_lvl;
|
||||
int j;
|
||||
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
/* Default clock levels are used for diags, which may lead to overclocking. */
|
||||
if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
|
||||
dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
|
||||
dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
|
||||
dcn3_01_soc.num_chans = bw_params->num_channels;
|
||||
|
||||
ASSERT(clk_table->num_entries);
|
||||
for (i = 0; i < clk_table->num_entries; i++) {
|
||||
/* loop backwards*/
|
||||
for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
|
||||
if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
|
||||
closest_clk_lvl = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clock_limits[i].state = i;
|
||||
clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
|
||||
clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
|
||||
clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
|
||||
clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
|
||||
|
||||
clock_limits[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
|
||||
clock_limits[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
|
||||
clock_limits[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
|
||||
clock_limits[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
|
||||
clock_limits[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
|
||||
clock_limits[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
|
||||
clock_limits[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
|
||||
}
|
||||
|
||||
for (i = 0; i < clk_table->num_entries; i++)
|
||||
dcn3_01_soc.clock_limits[i] = clock_limits[i];
|
||||
|
||||
if (clk_table->num_entries) {
|
||||
dcn3_01_soc.num_states = clk_table->num_entries;
|
||||
/* duplicate last level */
|
||||
dcn3_01_soc.clock_limits[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
|
||||
dcn3_01_soc.clock_limits[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
|
||||
}
|
||||
}
|
||||
|
||||
dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
|
||||
|
||||
dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
|
||||
}
|
||||
|
||||
void dcn301_fpu_set_wm_ranges(int i,
|
||||
struct pp_smu_wm_range_sets *ranges,
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
|
||||
{
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
ranges->reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
|
||||
ranges->reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
|
||||
}
|
||||
|
||||
void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info)
|
||||
{
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
if (bb_info.dram_clock_change_latency_100ns > 0)
|
||||
dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
|
||||
|
||||
if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
|
||||
dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
|
||||
|
||||
if (bb_info.dram_sr_exit_latency_100ns > 0)
|
||||
dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
|
||||
}
|
||||
|
||||
void dcn301_calculate_wm_and_dlg(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
int vlevel_req)
|
||||
{
|
||||
int i, pipe_idx;
|
||||
int vlevel, vlevel_max;
|
||||
struct wm_range_table_entry *table_entry;
|
||||
struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
|
||||
|
||||
ASSERT(bw_params);
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
vlevel_max = bw_params->clk_table.num_entries - 1;
|
||||
|
||||
/* WM Set D */
|
||||
table_entry = &bw_params->wm_table.entries[WM_D];
|
||||
if (table_entry->wm_type == WM_TYPE_RETRAINING)
|
||||
vlevel = 0;
|
||||
else
|
||||
vlevel = vlevel_max;
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set C */
|
||||
table_entry = &bw_params->wm_table.entries[WM_C];
|
||||
vlevel = min(max(vlevel_req, 2), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set B */
|
||||
table_entry = &bw_params->wm_table.entries[WM_B];
|
||||
vlevel = min(max(vlevel_req, 1), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
/* WM Set A */
|
||||
table_entry = &bw_params->wm_table.entries[WM_A];
|
||||
vlevel = min(vlevel_req, vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (!context->res_ctx.pipe_ctx[i].stream)
|
||||
continue;
|
||||
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
|
||||
if (dc->config.forced_clocks) {
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
|
||||
}
|
||||
if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
|
||||
if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
|
||||
pipe_idx++;
|
||||
}
|
||||
|
||||
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
|
||||
}
|
42
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
Normal file
42
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019-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 __DCN301_FPU_H__
|
||||
#define __DCN301_FPU_H__
|
||||
|
||||
void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
|
||||
|
||||
void dcn301_fpu_set_wm_ranges(int i,
|
||||
struct pp_smu_wm_range_sets *ranges,
|
||||
struct _vcs_dpi_soc_bounding_box_st *loaded_bb);
|
||||
|
||||
void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info);
|
||||
|
||||
void dcn301_calculate_wm_and_dlg(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
int vlevel_req);
|
||||
#endif /* __DCN301_FPU_H__*/
|
291
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
Normal file
291
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* 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 "rc_calc_fpu.h"
|
||||
|
||||
#include "qp_tables.h"
|
||||
#include "amdgpu_dm/dc_fpu.h"
|
||||
|
||||
#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
|
||||
|
||||
#define MODE_SELECT(val444, val422, val420) \
|
||||
(cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
|
||||
|
||||
|
||||
#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \
|
||||
table = qp_table_##mode##_##bpc##bpc_##max; \
|
||||
table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
|
||||
break
|
||||
|
||||
static int median3(int a, int b, int c)
|
||||
{
|
||||
if (a > b)
|
||||
swap(a, b);
|
||||
if (b > c)
|
||||
swap(b, c);
|
||||
if (a > b)
|
||||
swap(b, c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static double dsc_roundf(double num)
|
||||
{
|
||||
if (num < 0.0)
|
||||
num = num - 0.5;
|
||||
else
|
||||
num = num + 0.5;
|
||||
|
||||
return (int)(num);
|
||||
}
|
||||
|
||||
static double dsc_ceil(double num)
|
||||
{
|
||||
double retval = (int)num;
|
||||
|
||||
if (retval != num && num > 0)
|
||||
retval = num + 1;
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
|
||||
enum max_min max_min, float bpp)
|
||||
{
|
||||
int mode = MODE_SELECT(444, 422, 420);
|
||||
int sel = table_hash(mode, bpc, max_min);
|
||||
int table_size = 0;
|
||||
int index;
|
||||
const struct qp_entry *table = 0L;
|
||||
|
||||
// alias enum
|
||||
enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
|
||||
switch (sel) {
|
||||
TABLE_CASE(444, 8, max);
|
||||
TABLE_CASE(444, 8, min);
|
||||
TABLE_CASE(444, 10, max);
|
||||
TABLE_CASE(444, 10, min);
|
||||
TABLE_CASE(444, 12, max);
|
||||
TABLE_CASE(444, 12, min);
|
||||
TABLE_CASE(422, 8, max);
|
||||
TABLE_CASE(422, 8, min);
|
||||
TABLE_CASE(422, 10, max);
|
||||
TABLE_CASE(422, 10, min);
|
||||
TABLE_CASE(422, 12, max);
|
||||
TABLE_CASE(422, 12, min);
|
||||
TABLE_CASE(420, 8, max);
|
||||
TABLE_CASE(420, 8, min);
|
||||
TABLE_CASE(420, 10, max);
|
||||
TABLE_CASE(420, 10, min);
|
||||
TABLE_CASE(420, 12, max);
|
||||
TABLE_CASE(420, 12, min);
|
||||
}
|
||||
|
||||
if (table == 0)
|
||||
return;
|
||||
|
||||
index = (bpp - table[0].bpp) * 2;
|
||||
|
||||
/* requested size is bigger than the table */
|
||||
if (index >= table_size) {
|
||||
dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(qps, table[index].qps, sizeof(qp_set));
|
||||
}
|
||||
|
||||
static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
|
||||
{
|
||||
int *p = ofs;
|
||||
|
||||
if (mode == CM_444 || mode == CM_RGB) {
|
||||
*p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else if (mode == CM_422) {
|
||||
*p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else {
|
||||
*p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
}
|
||||
}
|
||||
|
||||
void _do_calc_rc_params(struct rc_params *rc,
|
||||
enum colour_mode cm,
|
||||
enum bits_per_comp bpc,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width,
|
||||
int slice_height,
|
||||
int minor_version)
|
||||
{
|
||||
float bpp;
|
||||
float bpp_group;
|
||||
float initial_xmit_delay_factor;
|
||||
int padding_pixels;
|
||||
int i;
|
||||
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
/* in native_422 or native_420 modes, the bits_per_pixel is double the
|
||||
* target bpp (the latter is what calc_rc_params expects)
|
||||
*/
|
||||
if (is_navite_422_or_420)
|
||||
bpp /= 2.0;
|
||||
|
||||
rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
|
||||
bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
|
||||
|
||||
switch (cm) {
|
||||
case CM_420:
|
||||
rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
break;
|
||||
case CM_422:
|
||||
rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
case CM_444:
|
||||
case CM_RGB:
|
||||
rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
|
||||
rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
|
||||
|
||||
if (cm == CM_422 || cm == CM_420)
|
||||
slice_width /= 2;
|
||||
|
||||
padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
|
||||
if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
|
||||
if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
|
||||
rc->initial_xmit_delay++;
|
||||
}
|
||||
|
||||
rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_det_thresh = 2 << (bpc - 8);
|
||||
|
||||
get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
|
||||
get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
|
||||
if (cm == CM_444 && minor_version == 1) {
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
|
||||
rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
|
||||
}
|
||||
}
|
||||
get_ofs_set(rc->ofs, cm, bpp);
|
||||
|
||||
/* fixed parameters */
|
||||
rc->rc_model_size = 8192;
|
||||
rc->rc_edge_factor = 6;
|
||||
rc->rc_tgt_offset_hi = 3;
|
||||
rc->rc_tgt_offset_lo = 3;
|
||||
|
||||
rc->rc_buf_thresh[0] = 896;
|
||||
rc->rc_buf_thresh[1] = 1792;
|
||||
rc->rc_buf_thresh[2] = 2688;
|
||||
rc->rc_buf_thresh[3] = 3584;
|
||||
rc->rc_buf_thresh[4] = 4480;
|
||||
rc->rc_buf_thresh[5] = 5376;
|
||||
rc->rc_buf_thresh[6] = 6272;
|
||||
rc->rc_buf_thresh[7] = 6720;
|
||||
rc->rc_buf_thresh[8] = 7168;
|
||||
rc->rc_buf_thresh[9] = 7616;
|
||||
rc->rc_buf_thresh[10] = 7744;
|
||||
rc->rc_buf_thresh[11] = 7872;
|
||||
rc->rc_buf_thresh[12] = 8000;
|
||||
rc->rc_buf_thresh[13] = 8064;
|
||||
}
|
||||
|
||||
u32 _do_bytes_per_pixel_calc(int slice_width,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420)
|
||||
{
|
||||
float bpp;
|
||||
u32 bytes_per_pixel;
|
||||
double d_bytes_per_pixel;
|
||||
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
|
||||
// TODO: Make sure the formula for calculating this is precise (ceiling
|
||||
// vs. floor, and at what point they should be applied)
|
||||
if (is_navite_422_or_420)
|
||||
d_bytes_per_pixel /= 2;
|
||||
|
||||
bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
|
||||
|
||||
return bytes_per_pixel;
|
||||
}
|
94
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
Normal file
94
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 __RC_CALC_FPU_H__
|
||||
#define __RC_CALC_FPU_H__
|
||||
|
||||
#include "os_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#define QP_SET_SIZE 15
|
||||
|
||||
typedef int qp_set[QP_SET_SIZE];
|
||||
|
||||
struct rc_params {
|
||||
int rc_quant_incr_limit0;
|
||||
int rc_quant_incr_limit1;
|
||||
int initial_fullness_offset;
|
||||
int initial_xmit_delay;
|
||||
int first_line_bpg_offset;
|
||||
int second_line_bpg_offset;
|
||||
int flatness_min_qp;
|
||||
int flatness_max_qp;
|
||||
int flatness_det_thresh;
|
||||
qp_set qp_min;
|
||||
qp_set qp_max;
|
||||
qp_set ofs;
|
||||
int rc_model_size;
|
||||
int rc_edge_factor;
|
||||
int rc_tgt_offset_hi;
|
||||
int rc_tgt_offset_lo;
|
||||
int rc_buf_thresh[QP_SET_SIZE - 1];
|
||||
};
|
||||
|
||||
enum colour_mode {
|
||||
CM_RGB, /* 444 RGB */
|
||||
CM_444, /* 444 YUV or simple 422 */
|
||||
CM_422, /* native 422 */
|
||||
CM_420 /* native 420 */
|
||||
};
|
||||
|
||||
enum bits_per_comp {
|
||||
BPC_8 = 8,
|
||||
BPC_10 = 10,
|
||||
BPC_12 = 12
|
||||
};
|
||||
|
||||
enum max_min {
|
||||
DAL_MM_MIN = 0,
|
||||
DAL_MM_MAX = 1
|
||||
};
|
||||
|
||||
struct qp_entry {
|
||||
float bpp;
|
||||
const qp_set qps;
|
||||
};
|
||||
|
||||
typedef struct qp_entry qp_table[];
|
||||
|
||||
u32 _do_bytes_per_pixel_calc(int slice_width,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420);
|
||||
|
||||
void _do_calc_rc_params(struct rc_params *rc,
|
||||
enum colour_mode cm,
|
||||
enum bits_per_comp bpc,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width,
|
||||
int slice_height,
|
||||
int minor_version);
|
||||
|
||||
#endif
|
@ -1,35 +1,6 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Makefile for the 'dsc' sub-component of DAL.
|
||||
|
||||
ifdef CONFIG_X86
|
||||
dsc_ccflags := -mhard-float -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
dsc_ccflags := -mhard-float -maltivec
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_IS_GCC
|
||||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
ifdef IS_OLD_GCC
|
||||
# Stack alignment mismatch, proceed with caution.
|
||||
# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
|
||||
# (8B stack alignment).
|
||||
dsc_ccflags += -mpreferred-stack-boundary=4
|
||||
else
|
||||
dsc_ccflags += -msse2
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags)
|
||||
|
||||
DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
|
||||
|
||||
AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC))
|
||||
|
@ -23,266 +23,7 @@
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#include "os_types.h"
|
||||
#include "rc_calc.h"
|
||||
#include "qp_tables.h"
|
||||
|
||||
#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
|
||||
|
||||
#define MODE_SELECT(val444, val422, val420) \
|
||||
(cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
|
||||
|
||||
|
||||
#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \
|
||||
table = qp_table_##mode##_##bpc##bpc_##max; \
|
||||
table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
|
||||
break
|
||||
|
||||
|
||||
static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
|
||||
enum max_min max_min, float bpp)
|
||||
{
|
||||
int mode = MODE_SELECT(444, 422, 420);
|
||||
int sel = table_hash(mode, bpc, max_min);
|
||||
int table_size = 0;
|
||||
int index;
|
||||
const struct qp_entry *table = 0L;
|
||||
|
||||
// alias enum
|
||||
enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
|
||||
switch (sel) {
|
||||
TABLE_CASE(444, 8, max);
|
||||
TABLE_CASE(444, 8, min);
|
||||
TABLE_CASE(444, 10, max);
|
||||
TABLE_CASE(444, 10, min);
|
||||
TABLE_CASE(444, 12, max);
|
||||
TABLE_CASE(444, 12, min);
|
||||
TABLE_CASE(422, 8, max);
|
||||
TABLE_CASE(422, 8, min);
|
||||
TABLE_CASE(422, 10, max);
|
||||
TABLE_CASE(422, 10, min);
|
||||
TABLE_CASE(422, 12, max);
|
||||
TABLE_CASE(422, 12, min);
|
||||
TABLE_CASE(420, 8, max);
|
||||
TABLE_CASE(420, 8, min);
|
||||
TABLE_CASE(420, 10, max);
|
||||
TABLE_CASE(420, 10, min);
|
||||
TABLE_CASE(420, 12, max);
|
||||
TABLE_CASE(420, 12, min);
|
||||
}
|
||||
|
||||
if (table == 0)
|
||||
return;
|
||||
|
||||
index = (bpp - table[0].bpp) * 2;
|
||||
|
||||
/* requested size is bigger than the table */
|
||||
if (index >= table_size) {
|
||||
dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(qps, table[index].qps, sizeof(qp_set));
|
||||
}
|
||||
|
||||
static double dsc_roundf(double num)
|
||||
{
|
||||
if (num < 0.0)
|
||||
num = num - 0.5;
|
||||
else
|
||||
num = num + 0.5;
|
||||
|
||||
return (int)(num);
|
||||
}
|
||||
|
||||
static double dsc_ceil(double num)
|
||||
{
|
||||
double retval = (int)num;
|
||||
|
||||
if (retval != num && num > 0)
|
||||
retval = num + 1;
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
|
||||
{
|
||||
int *p = ofs;
|
||||
|
||||
if (mode == CM_444 || mode == CM_RGB) {
|
||||
*p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else if (mode == CM_422) {
|
||||
*p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else {
|
||||
*p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
}
|
||||
}
|
||||
|
||||
static int median3(int a, int b, int c)
|
||||
{
|
||||
if (a > b)
|
||||
swap(a, b);
|
||||
if (b > c)
|
||||
swap(b, c);
|
||||
if (a > b)
|
||||
swap(b, c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm,
|
||||
enum bits_per_comp bpc, u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width, int slice_height,
|
||||
int minor_version)
|
||||
{
|
||||
float bpp;
|
||||
float bpp_group;
|
||||
float initial_xmit_delay_factor;
|
||||
int padding_pixels;
|
||||
int i;
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
/* in native_422 or native_420 modes, the bits_per_pixel is double the
|
||||
* target bpp (the latter is what calc_rc_params expects)
|
||||
*/
|
||||
if (is_navite_422_or_420)
|
||||
bpp /= 2.0;
|
||||
|
||||
rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
|
||||
bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
|
||||
|
||||
switch (cm) {
|
||||
case CM_420:
|
||||
rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
break;
|
||||
case CM_422:
|
||||
rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
case CM_444:
|
||||
case CM_RGB:
|
||||
rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
|
||||
rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
|
||||
|
||||
if (cm == CM_422 || cm == CM_420)
|
||||
slice_width /= 2;
|
||||
|
||||
padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
|
||||
if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
|
||||
if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
|
||||
rc->initial_xmit_delay++;
|
||||
}
|
||||
|
||||
rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_det_thresh = 2 << (bpc - 8);
|
||||
|
||||
get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
|
||||
get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
|
||||
if (cm == CM_444 && minor_version == 1) {
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
|
||||
rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
|
||||
}
|
||||
}
|
||||
get_ofs_set(rc->ofs, cm, bpp);
|
||||
|
||||
/* fixed parameters */
|
||||
rc->rc_model_size = 8192;
|
||||
rc->rc_edge_factor = 6;
|
||||
rc->rc_tgt_offset_hi = 3;
|
||||
rc->rc_tgt_offset_lo = 3;
|
||||
|
||||
rc->rc_buf_thresh[0] = 896;
|
||||
rc->rc_buf_thresh[1] = 1792;
|
||||
rc->rc_buf_thresh[2] = 2688;
|
||||
rc->rc_buf_thresh[3] = 3584;
|
||||
rc->rc_buf_thresh[4] = 4480;
|
||||
rc->rc_buf_thresh[5] = 5376;
|
||||
rc->rc_buf_thresh[6] = 6272;
|
||||
rc->rc_buf_thresh[7] = 6720;
|
||||
rc->rc_buf_thresh[8] = 7168;
|
||||
rc->rc_buf_thresh[9] = 7616;
|
||||
rc->rc_buf_thresh[10] = 7744;
|
||||
rc->rc_buf_thresh[11] = 7872;
|
||||
rc->rc_buf_thresh[12] = 8000;
|
||||
rc->rc_buf_thresh[13] = 8064;
|
||||
}
|
||||
|
||||
static u32 _do_bytes_per_pixel_calc(int slice_width, u16 drm_bpp,
|
||||
bool is_navite_422_or_420)
|
||||
{
|
||||
float bpp;
|
||||
u32 bytes_per_pixel;
|
||||
double d_bytes_per_pixel;
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
|
||||
// TODO: Make sure the formula for calculating this is precise (ceiling
|
||||
// vs. floor, and at what point they should be applied)
|
||||
if (is_navite_422_or_420)
|
||||
d_bytes_per_pixel /= 2;
|
||||
|
||||
bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
|
||||
|
||||
return bytes_per_pixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* calc_rc_params - reads the user's cmdline mode
|
||||
|
@ -27,55 +27,7 @@
|
||||
#ifndef __RC_CALC_H__
|
||||
#define __RC_CALC_H__
|
||||
|
||||
|
||||
#define QP_SET_SIZE 15
|
||||
|
||||
typedef int qp_set[QP_SET_SIZE];
|
||||
|
||||
struct rc_params {
|
||||
int rc_quant_incr_limit0;
|
||||
int rc_quant_incr_limit1;
|
||||
int initial_fullness_offset;
|
||||
int initial_xmit_delay;
|
||||
int first_line_bpg_offset;
|
||||
int second_line_bpg_offset;
|
||||
int flatness_min_qp;
|
||||
int flatness_max_qp;
|
||||
int flatness_det_thresh;
|
||||
qp_set qp_min;
|
||||
qp_set qp_max;
|
||||
qp_set ofs;
|
||||
int rc_model_size;
|
||||
int rc_edge_factor;
|
||||
int rc_tgt_offset_hi;
|
||||
int rc_tgt_offset_lo;
|
||||
int rc_buf_thresh[QP_SET_SIZE - 1];
|
||||
};
|
||||
|
||||
enum colour_mode {
|
||||
CM_RGB, /* 444 RGB */
|
||||
CM_444, /* 444 YUV or simple 422 */
|
||||
CM_422, /* native 422 */
|
||||
CM_420 /* native 420 */
|
||||
};
|
||||
|
||||
enum bits_per_comp {
|
||||
BPC_8 = 8,
|
||||
BPC_10 = 10,
|
||||
BPC_12 = 12
|
||||
};
|
||||
|
||||
enum max_min {
|
||||
DAL_MM_MIN = 0,
|
||||
DAL_MM_MAX = 1
|
||||
};
|
||||
|
||||
struct qp_entry {
|
||||
float bpp;
|
||||
const qp_set qps;
|
||||
};
|
||||
|
||||
typedef struct qp_entry qp_table[];
|
||||
#include "dml/dsc/rc_calc_fpu.h"
|
||||
|
||||
void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps);
|
||||
u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps);
|
||||
|
@ -22,7 +22,6 @@
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
#include "os_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
#include "dscc_types.h"
|
||||
#include "rc_calc.h"
|
||||
|
@ -121,12 +121,12 @@ enum dc_status dpcd_set_lane_settings(
|
||||
const struct link_training_settings *link_training_setting,
|
||||
uint32_t offset);
|
||||
/* Read training status and adjustment requests from DPCD. */
|
||||
enum dc_status dp_get_lane_status_and_drive_settings(
|
||||
enum dc_status dp_get_lane_status_and_lane_adjust(
|
||||
struct dc_link *link,
|
||||
const struct link_training_settings *link_training_setting,
|
||||
union lane_status *ln_status,
|
||||
union lane_align_status_updated *ln_status_updated,
|
||||
struct link_training_settings *req_settings,
|
||||
union lane_status ln_status[LANE_COUNT_DP_MAX],
|
||||
union lane_align_status_updated *ln_align,
|
||||
union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
uint32_t offset);
|
||||
|
||||
void dp_wait_for_training_aux_rd_interval(
|
||||
@ -151,9 +151,11 @@ void dp_hw_to_dpcd_lane_settings(
|
||||
const struct link_training_settings *lt_settings,
|
||||
const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
|
||||
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]);
|
||||
void dp_update_drive_settings(
|
||||
struct link_training_settings *dest,
|
||||
struct link_training_settings src);
|
||||
void dp_decide_lane_settings(
|
||||
const struct link_training_settings *lt_settings,
|
||||
const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
|
||||
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
|
||||
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]);
|
||||
|
||||
uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval);
|
||||
|
||||
|
@ -34,6 +34,8 @@ union defer_reg_writes {
|
||||
bool disable_blnd_lut:1;
|
||||
bool disable_3dlut:1;
|
||||
bool disable_shaper:1;
|
||||
bool disable_gamcor:1;
|
||||
bool disable_dscl:1;
|
||||
} bits;
|
||||
uint32_t raw;
|
||||
};
|
||||
|
@ -97,6 +97,7 @@ enum dmub_asic {
|
||||
DMUB_ASIC_DCN302,
|
||||
DMUB_ASIC_DCN303,
|
||||
DMUB_ASIC_DCN31,
|
||||
DMUB_ASIC_DCN31B,
|
||||
DMUB_ASIC_MAX,
|
||||
};
|
||||
|
||||
@ -237,6 +238,7 @@ struct dmub_srv_hw_params {
|
||||
bool load_inst_const;
|
||||
bool skip_panel_power_sequence;
|
||||
bool disable_z10;
|
||||
bool dpia_supported;
|
||||
bool disable_dpia;
|
||||
};
|
||||
|
||||
|
@ -46,10 +46,10 @@
|
||||
|
||||
/* Firmware versioning. */
|
||||
#ifdef DMUB_EXPOSE_VERSION
|
||||
#define DMUB_FW_VERSION_GIT_HASH 0xd146258f
|
||||
#define DMUB_FW_VERSION_GIT_HASH 0x9525efb5
|
||||
#define DMUB_FW_VERSION_MAJOR 0
|
||||
#define DMUB_FW_VERSION_MINOR 0
|
||||
#define DMUB_FW_VERSION_REVISION 88
|
||||
#define DMUB_FW_VERSION_REVISION 90
|
||||
#define DMUB_FW_VERSION_TEST 0
|
||||
#define DMUB_FW_VERSION_VBIOS 0
|
||||
#define DMUB_FW_VERSION_HOTFIX 0
|
||||
@ -370,8 +370,13 @@ union dmub_fw_boot_options {
|
||||
uint32_t z10_disable: 1; /**< 1 to disable z10 */
|
||||
uint32_t enable_dpia: 1; /**< 1 if DPIA should be enabled */
|
||||
uint32_t invalid_vbios_data: 1; /**< 1 if VBIOS data table is invalid */
|
||||
uint32_t reserved_unreleased2: 1; /**< reserved for an unreleased feature */
|
||||
uint32_t reserved : 22; /**< reserved */
|
||||
uint32_t dpia_supported: 1; /**< 1 if DPIA is supported on this platform */
|
||||
uint32_t sel_mux_phy_c_d_phy_f_g: 1; /**< 1 if PHYF/PHYG should be enabled */
|
||||
/**< 1 if all root clock gating is enabled and low power memory is enabled*/
|
||||
uint32_t power_optimization: 1;
|
||||
uint32_t diag_env: 1; /* 1 if diagnostic environment */
|
||||
|
||||
uint32_t reserved : 19; /**< reserved */
|
||||
} bits; /**< boot bits */
|
||||
uint32_t all; /**< 32-bit access to bits */
|
||||
};
|
||||
@ -692,6 +697,7 @@ enum dmub_out_cmd_type {
|
||||
enum dmub_cmd_dpia_type {
|
||||
DMUB_CMD__DPIA_DIG1_DPIA_CONTROL = 0,
|
||||
DMUB_CMD__DPIA_SET_CONFIG_ACCESS = 1,
|
||||
DMUB_CMD__DPIA_MST_ALLOC_SLOTS = 2,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@ -1066,6 +1072,24 @@ struct dmub_rb_cmd_set_config_access {
|
||||
struct dmub_cmd_set_config_control_data set_config_control; /* set config data */
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed from driver to FW in a DMUB_CMD__DPIA_MST_ALLOC_SLOTS command.
|
||||
*/
|
||||
struct dmub_cmd_mst_alloc_slots_control_data {
|
||||
uint8_t mst_alloc_slots; /* mst slots to be allotted */
|
||||
uint8_t instance; /* DPIA instance */
|
||||
uint8_t immed_status; /* Immediate status returned as there is no outbox msg posted */
|
||||
uint8_t mst_slots_in_use; /* returns slots in use for error cases */
|
||||
};
|
||||
|
||||
/**
|
||||
* DMUB command structure for SET_ command.
|
||||
*/
|
||||
struct dmub_rb_cmd_set_mst_alloc_slots {
|
||||
struct dmub_cmd_header header; /* header */
|
||||
struct dmub_cmd_mst_alloc_slots_control_data mst_slots_control; /* mst slots control */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dmub_rb_cmd_dpphy_init - DPPHY init.
|
||||
*/
|
||||
@ -1378,6 +1402,10 @@ enum dmub_cmd_psr_type {
|
||||
* Forces PSR enabled until an explicit PSR disable call.
|
||||
*/
|
||||
DMUB_CMD__PSR_FORCE_STATIC = 5,
|
||||
/**
|
||||
* Set PSR power option
|
||||
*/
|
||||
DMUB_CMD__SET_PSR_POWER_OPT = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1675,6 +1703,44 @@ struct dmub_rb_cmd_psr_force_static {
|
||||
struct dmub_cmd_psr_force_static_data psr_force_static_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed from driver to FW in a DMUB_CMD__SET_PSR_POWER_OPT command.
|
||||
*/
|
||||
struct dmub_cmd_psr_set_power_opt_data {
|
||||
/**
|
||||
* PSR control version.
|
||||
*/
|
||||
uint8_t cmd_version;
|
||||
/**
|
||||
* Panel Instance.
|
||||
* Panel isntance to identify which psr_state to use
|
||||
* Currently the support is only for 0 or 1
|
||||
*/
|
||||
uint8_t panel_inst;
|
||||
/**
|
||||
* Explicit padding to 4 byte boundary.
|
||||
*/
|
||||
uint8_t pad[2];
|
||||
/**
|
||||
* PSR power option
|
||||
*/
|
||||
uint32_t power_opt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition of a DMUB_CMD__SET_PSR_POWER_OPT command.
|
||||
*/
|
||||
struct dmub_rb_cmd_psr_set_power_opt {
|
||||
/**
|
||||
* Command header.
|
||||
*/
|
||||
struct dmub_cmd_header header;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__SET_PSR_POWER_OPT command.
|
||||
*/
|
||||
struct dmub_cmd_psr_set_power_opt_data psr_set_power_opt_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set of HW components that can be locked.
|
||||
*
|
||||
@ -2458,6 +2524,10 @@ union dmub_rb_cmd {
|
||||
* Definition of a DMUB_CMD__PSR_FORCE_STATIC command.
|
||||
*/
|
||||
struct dmub_rb_cmd_psr_force_static psr_force_static;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__SET_PSR_POWER_OPT command.
|
||||
*/
|
||||
struct dmub_rb_cmd_psr_set_power_opt psr_set_power_opt;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__PLAT_54186_WA command.
|
||||
*/
|
||||
@ -2542,6 +2612,10 @@ union dmub_rb_cmd {
|
||||
* Definition of a DMUB_CMD__DPIA_SET_CONFIG_ACCESS command.
|
||||
*/
|
||||
struct dmub_rb_cmd_set_config_access set_config_access;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__DPIA_MST_ALLOC_SLOTS command.
|
||||
*/
|
||||
struct dmub_rb_cmd_set_mst_alloc_slots set_mst_alloc_slots;
|
||||
/**
|
||||
* Definition of a DMUB_CMD__EDID_CEA command.
|
||||
*/
|
||||
|
@ -338,8 +338,11 @@ void dmub_dcn31_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
|
||||
union dmub_fw_boot_options boot_options = {0};
|
||||
|
||||
boot_options.bits.z10_disable = params->disable_z10;
|
||||
boot_options.bits.dpia_supported = params->dpia_supported;
|
||||
boot_options.bits.enable_dpia = params->disable_dpia ? 0 : 1;
|
||||
|
||||
boot_options.bits.sel_mux_phy_c_d_phy_f_g = (dmub->asic == DMUB_ASIC_DCN31B) ? 1 : 0;
|
||||
|
||||
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
|
||||
break;
|
||||
|
||||
case DMUB_ASIC_DCN31:
|
||||
case DMUB_ASIC_DCN31B:
|
||||
dmub->regs_dcn31 = &dmub_srv_dcn31_regs;
|
||||
funcs->reset = dmub_dcn31_reset;
|
||||
funcs->reset_release = dmub_dcn31_reset_release;
|
||||
|
@ -328,6 +328,7 @@ struct integrated_info {
|
||||
|
||||
uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID];
|
||||
uint8_t checksum;
|
||||
uint8_t fixdpvoltageswing;
|
||||
} ext_disp_conn_info; /* exiting long long time */
|
||||
|
||||
struct available_s_clk_list {
|
||||
|
@ -41,6 +41,8 @@ struct aux_payload {
|
||||
* reset it to read data */
|
||||
bool write;
|
||||
bool mot;
|
||||
bool write_status_update;
|
||||
|
||||
uint32_t address;
|
||||
uint32_t length;
|
||||
uint8_t *data;
|
||||
@ -53,6 +55,7 @@ struct aux_payload {
|
||||
* zero means "use default value"
|
||||
*/
|
||||
uint32_t defer_delay;
|
||||
|
||||
};
|
||||
|
||||
struct aux_command {
|
||||
|
@ -90,8 +90,11 @@ enum lttpr_mode {
|
||||
|
||||
struct link_training_settings {
|
||||
struct dc_link_settings link_settings;
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
|
||||
|
||||
/* TODO: turn lane settings below into mandatory fields
|
||||
* as initial lane configuration
|
||||
*/
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
|
||||
enum dc_voltage_swing *voltage_swing;
|
||||
enum dc_pre_emphasis *pre_emphasis;
|
||||
enum dc_post_cursor2 *post_cursor2;
|
||||
@ -115,8 +118,30 @@ struct link_training_settings {
|
||||
#endif
|
||||
|
||||
bool enhanced_framing;
|
||||
bool allow_invalid_msa_timing_param;
|
||||
enum lttpr_mode lttpr_mode;
|
||||
|
||||
/* disallow different lanes to have different lane settings */
|
||||
bool disallow_per_lane_settings;
|
||||
/* dpcd lane settings will always use the same hw lane settings
|
||||
* even if it doesn't match requested lane adjust */
|
||||
bool always_match_dpcd_with_hw_lane_settings;
|
||||
|
||||
/*****************************************************************
|
||||
* training states - parameters that can change in link training
|
||||
*****************************************************************/
|
||||
/* TODO: Move hw_lane_settings and dpcd_lane_settings
|
||||
* along with lane adjust, lane align, offset and all
|
||||
* other training states into a new structure called
|
||||
* training states, so link_training_settings becomes
|
||||
* a constant input pre-decided prior to link training.
|
||||
*
|
||||
* The goal is to strictly decouple link training settings
|
||||
* decision making process from link training states to
|
||||
* prevent it from messy code practice of changing training
|
||||
* decision on the fly.
|
||||
*/
|
||||
struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX];
|
||||
union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX];
|
||||
};
|
||||
|
||||
/*TODO: Move this enum test harness*/
|
||||
|
@ -155,9 +155,18 @@ static unsigned int calc_v_total_from_duration(
|
||||
if (duration_in_us > vrr->max_duration_in_us)
|
||||
duration_in_us = vrr->max_duration_in_us;
|
||||
|
||||
v_total = div64_u64(div64_u64(((unsigned long long)(
|
||||
duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
|
||||
stream->timing.h_total), 1000);
|
||||
if (dc_is_hdmi_signal(stream->signal)) {
|
||||
uint32_t h_total_up_scaled;
|
||||
|
||||
h_total_up_scaled = stream->timing.h_total * 10000;
|
||||
v_total = div_u64((unsigned long long)duration_in_us
|
||||
* stream->timing.pix_clk_100hz + (h_total_up_scaled - 1),
|
||||
h_total_up_scaled);
|
||||
} else {
|
||||
v_total = div64_u64(div64_u64(((unsigned long long)(
|
||||
duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
|
||||
stream->timing.h_total), 1000);
|
||||
}
|
||||
|
||||
/* v_total cannot be less than nominal */
|
||||
if (v_total < stream->timing.v_total) {
|
||||
|
@ -105,6 +105,7 @@ static enum mod_hdcp_status remove_display_from_topology_v3(
|
||||
dtm_cmd->dtm_status = TA_DTM_STATUS__GENERIC_FAILURE;
|
||||
|
||||
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
|
||||
mutex_unlock(&psp->dtm_context.mutex);
|
||||
|
||||
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
|
||||
status = remove_display_from_topology_v2(hdcp, index);
|
||||
@ -115,8 +116,6 @@ static enum mod_hdcp_status remove_display_from_topology_v3(
|
||||
HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index);
|
||||
}
|
||||
|
||||
mutex_unlock(&psp->dtm_context.mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -205,6 +204,7 @@ static enum mod_hdcp_status add_display_to_topology_v3(
|
||||
dtm_cmd->dtm_in_message.topology_update_v3.link_hdcp_cap = link->hdcp_supported_informational;
|
||||
|
||||
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
|
||||
mutex_unlock(&psp->dtm_context.mutex);
|
||||
|
||||
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
|
||||
status = add_display_to_topology_v2(hdcp, display);
|
||||
@ -214,8 +214,6 @@ static enum mod_hdcp_status add_display_to_topology_v3(
|
||||
HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index);
|
||||
}
|
||||
|
||||
mutex_unlock(&psp->dtm_context.mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -249,6 +249,8 @@ struct mod_hdcp_link {
|
||||
uint8_t ddc_line;
|
||||
uint8_t link_enc_idx;
|
||||
uint8_t phy_idx;
|
||||
uint8_t dio_output_type;
|
||||
uint8_t dio_output_id;
|
||||
uint8_t hdcp_supported_informational;
|
||||
union {
|
||||
struct mod_hdcp_displayport dp;
|
||||
|
@ -310,7 +310,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
enum amd_dpm_forced_level level;
|
||||
enum amd_dpm_forced_level current_level = 0xff;
|
||||
enum amd_dpm_forced_level current_level;
|
||||
int ret = 0;
|
||||
|
||||
if (amdgpu_in_reset(adev))
|
||||
@ -350,6 +350,8 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev,
|
||||
|
||||
if (pp_funcs->get_performance_level)
|
||||
current_level = amdgpu_dpm_get_performance_level(adev);
|
||||
else
|
||||
current_level = adev->pm.dpm.forced_level;
|
||||
|
||||
if (current_level == level) {
|
||||
pm_runtime_mark_last_busy(ddev->dev);
|
||||
|
@ -786,13 +786,6 @@ struct drm_amdgpu_cs_chunk_data {
|
||||
#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F
|
||||
/* query ras mask of enabled features*/
|
||||
#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20
|
||||
/* query video encode/decode caps */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS 0x21
|
||||
/* Subquery id: Decode */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS_DECODE 0
|
||||
/* Subquery id: Encode */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS_ENCODE 1
|
||||
|
||||
/* RAS MASK: UMC (VRAM) */
|
||||
#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0)
|
||||
/* RAS MASK: SDMA */
|
||||
@ -821,6 +814,12 @@ struct drm_amdgpu_cs_chunk_data {
|
||||
#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12)
|
||||
/* RAS MASK: FUSE */
|
||||
#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13)
|
||||
/* query video encode/decode caps */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS 0x21
|
||||
/* Subquery id: Decode */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS_DECODE 0
|
||||
/* Subquery id: Encode */
|
||||
#define AMDGPU_INFO_VIDEO_CAPS_ENCODE 1
|
||||
|
||||
#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
|
||||
#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
|
||||
|
Loading…
Reference in New Issue
Block a user