mirror of
https://github.com/torvalds/linux.git
synced 2024-10-23 21:50:43 +00:00
amd-drm-next-6.8-2024-01-05:
amdgpu: - VRR fixes - PSR-SU fixes - SubVP fixes - DCN 3.5 fixes - Documentation updates - DMCUB fixes - DML2 fixes - UMC 12.0 updates - GPUVM fix - Misc code cleanups and whitespace cleanups - DP MST fix - Let KFD sync with GPUVM fences - GFX11 reset fix - SMU 13.0.6 fixes - VSC fix for DP/eDP - Navi12 display fix - RN/CZN system aperture fix - DCN 2.1 bandwidth validation fix - DCN INIT cleanup amdkfd: - SVM fixes - Revert TBA/TMA location change -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZZh7ZQAKCRC93/aFa7yZ 2EPJAQDkoOlSjRLZoqwOPvBCo3WIzVO+4N6pOgohbTrjhHvDFAD+ONEgIH/wydk1 IOdtyizh9o7spo2qN2Oi06MDimclDg8= =bFa3 -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.8-2024-01-05' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-6.8-2024-01-05: amdgpu: - VRR fixes - PSR-SU fixes - SubVP fixes - DCN 3.5 fixes - Documentation updates - DMCUB fixes - DML2 fixes - UMC 12.0 updates - GPUVM fix - Misc code cleanups and whitespace cleanups - DP MST fix - Let KFD sync with GPUVM fences - GFX11 reset fix - SMU 13.0.6 fixes - VSC fix for DP/eDP - Navi12 display fix - RN/CZN system aperture fix - DCN 2.1 bandwidth validation fix - DCN INIT cleanup amdkfd: - SVM fixes - Revert TBA/TMA location change Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240105220522.4976-1-alexander.deucher@amd.com
This commit is contained in:
commit
e54478fbda
|
@ -7,6 +7,7 @@ SteamDeck, VANGOGH, DCN 3.0.1, 10.3.1, VCN 3.1.0, 5.2.1, 11.5.0
|
|||
Ryzen 5000 series / Ryzen 7x30 series, GREEN SARDINE / Cezanne / Barcelo / Barcelo-R, DCN 2.1, 9.3, VCN 2.2, 4.1.1, 12.0.1
|
||||
Ryzen 6000 series / Ryzen 7x35 series / Ryzen 7x36 series, YELLOW CARP / Rembrandt / Rembrandt-R, 3.1.2, 10.3.3, VCN 3.1.1, 5.2.3, 13.0.3
|
||||
Ryzen 7000 series (AM5), Raphael, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x45 series (FL1), / Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x45 series (FL1), Dragon Range, 3.1.5, 10.3.6, 3.1.2, 5.2.6, 13.0.5
|
||||
Ryzen 7x20 series, Mendocino, 3.1.6, 10.3.7, 3.1.1, 5.2.7, 13.0.8
|
||||
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
Ryzen 7x40 series, Phoenix, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
Ryzen 8x40 series, Hawk Point, 3.1.4, 11.0.1 / 11.0.4, 4.0.2, 6.0.1, 13.0.4 / 13.0.11
|
||||
|
|
|
|
@ -330,6 +330,7 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
|||
{
|
||||
struct list_head *reset_device_list = reset_context->reset_device_list;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
struct amdgpu_ras *con;
|
||||
int r;
|
||||
|
||||
if (reset_device_list == NULL)
|
||||
|
@ -355,7 +356,30 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
|||
*/
|
||||
amdgpu_register_gpu_instance(tmp_adev);
|
||||
|
||||
/* Resume RAS */
|
||||
/* Resume RAS, ecc_irq */
|
||||
con = amdgpu_ras_get_context(tmp_adev);
|
||||
if (!amdgpu_sriov_vf(tmp_adev) && con) {
|
||||
if (tmp_adev->sdma.ras &&
|
||||
tmp_adev->sdma.ras->ras_block.ras_late_init) {
|
||||
r = tmp_adev->sdma.ras->ras_block.ras_late_init(tmp_adev,
|
||||
&tmp_adev->sdma.ras->ras_block.ras_comm);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev, "SDMA failed to execute ras_late_init! ret:%d\n", r);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_adev->gfx.ras &&
|
||||
tmp_adev->gfx.ras->ras_block.ras_late_init) {
|
||||
r = tmp_adev->gfx.ras->ras_block.ras_late_init(tmp_adev,
|
||||
&tmp_adev->gfx.ras->ras_block.ras_comm);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev, "GFX failed to execute ras_late_init! ret:%d\n", r);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_ras_resume(tmp_adev);
|
||||
|
||||
/* Update PSP FW topology after reset */
|
||||
|
|
|
@ -254,6 +254,8 @@ extern int amdgpu_agp;
|
|||
|
||||
extern int amdgpu_wbrf;
|
||||
|
||||
extern int fw_bo_location;
|
||||
|
||||
#define AMDGPU_VM_MAX_NUM_CTX 4096
|
||||
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
|
||||
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
|
||||
|
|
|
@ -90,7 +90,7 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f)
|
|||
return NULL;
|
||||
|
||||
fence = container_of(f, struct amdgpu_amdkfd_fence, base);
|
||||
if (fence && f->ops == &amdkfd_fence_ops)
|
||||
if (f->ops == &amdkfd_fence_ops)
|
||||
return fence;
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -1103,7 +1103,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
|
|||
* DDC line. The latter is more complex because with DVI<->HDMI adapters
|
||||
* you don't really know what's connected to which port as both are digital.
|
||||
*/
|
||||
amdgpu_connector_shared_ddc(&ret, connector, amdgpu_connector);
|
||||
amdgpu_connector_shared_ddc(&ret, connector, amdgpu_connector);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -870,9 +870,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_bo *bo = e->bo;
|
||||
int i;
|
||||
|
||||
e->user_pages = kvmalloc_array(bo->tbo.ttm->num_pages,
|
||||
sizeof(struct page *),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
e->user_pages = kvcalloc(bo->tbo.ttm->num_pages,
|
||||
sizeof(struct page *),
|
||||
GFP_KERNEL);
|
||||
if (!e->user_pages) {
|
||||
DRM_ERROR("kvmalloc_array failure\n");
|
||||
r = -ENOMEM;
|
||||
|
|
|
@ -540,7 +540,11 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf,
|
|||
while (size) {
|
||||
uint32_t value;
|
||||
|
||||
value = RREG32_PCIE(*pos);
|
||||
if (upper_32_bits(*pos))
|
||||
value = RREG32_PCIE_EXT(*pos);
|
||||
else
|
||||
value = RREG32_PCIE(*pos);
|
||||
|
||||
r = put_user(value, (uint32_t *)buf);
|
||||
if (r)
|
||||
goto out;
|
||||
|
@ -600,7 +604,10 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
WREG32_PCIE(*pos, value);
|
||||
if (upper_32_bits(*pos))
|
||||
WREG32_PCIE_EXT(*pos, value);
|
||||
else
|
||||
WREG32_PCIE(*pos, value);
|
||||
|
||||
result += 4;
|
||||
buf += 4;
|
||||
|
|
|
@ -2251,15 +2251,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
|||
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
|
||||
if (adev->mman.discovery_bin) {
|
||||
/*
|
||||
* FIXME: The bounding box is still needed by Navi12, so
|
||||
* temporarily read it from gpu_info firmware. Should be dropped
|
||||
* when DAL no longer needs it.
|
||||
*/
|
||||
if (adev->asic_type != CHIP_NAVI12)
|
||||
return 0;
|
||||
}
|
||||
if (adev->mman.discovery_bin)
|
||||
return 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
default:
|
||||
|
|
|
@ -210,6 +210,7 @@ int amdgpu_seamless = -1; /* auto */
|
|||
uint amdgpu_debug_mask;
|
||||
int amdgpu_agp = -1; /* auto */
|
||||
int amdgpu_wbrf = -1;
|
||||
int fw_bo_location = -1;
|
||||
|
||||
static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
|
||||
|
||||
|
@ -989,6 +990,10 @@ MODULE_PARM_DESC(wbrf,
|
|||
"Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)");
|
||||
module_param_named(wbrf, amdgpu_wbrf, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(fw_bo_location,
|
||||
"location to put firmware bo for frontdoor loading (-1 = auto (default), 0 = on ram, 1 = on vram");
|
||||
module_param(fw_bo_location, int, 0644);
|
||||
|
||||
/* These devices are not supported by amdgpu.
|
||||
* They are supported by the mach64, r128, radeon drivers
|
||||
*/
|
||||
|
|
|
@ -218,6 +218,7 @@ static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, st
|
|||
int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data)
|
||||
{
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
struct ras_err_addr err_addr = {0};
|
||||
struct mca_bank_set mca_set;
|
||||
struct mca_bank_node *node;
|
||||
struct mca_bank_entry *entry;
|
||||
|
@ -246,10 +247,18 @@ int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_blo
|
|||
mcm_info.socket_id = entry->info.socket_id;
|
||||
mcm_info.die_id = entry->info.aid;
|
||||
|
||||
if (blk == AMDGPU_RAS_BLOCK__UMC) {
|
||||
err_addr.err_status = entry->regs[MCA_REG_IDX_STATUS];
|
||||
err_addr.err_ipid = entry->regs[MCA_REG_IDX_IPID];
|
||||
err_addr.err_addr = entry->regs[MCA_REG_IDX_ADDR];
|
||||
}
|
||||
|
||||
if (type == AMDGPU_MCA_ERROR_TYPE_UE)
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, (uint64_t)count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data,
|
||||
&mcm_info, &err_addr, (uint64_t)count);
|
||||
else
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, (uint64_t)count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data,
|
||||
&mcm_info, &err_addr, (uint64_t)count);
|
||||
}
|
||||
|
||||
out_mca_release:
|
||||
|
@ -351,6 +360,9 @@ int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_err
|
|||
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
|
||||
int count;
|
||||
|
||||
if (!mca_funcs || !mca_funcs->mca_get_mca_entry)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type) {
|
||||
case AMDGPU_MCA_ERROR_TYPE_UE:
|
||||
count = mca_funcs->max_ue_count;
|
||||
|
@ -365,10 +377,7 @@ int amdgpu_mca_smu_get_mca_entry(struct amdgpu_device *adev, enum amdgpu_mca_err
|
|||
if (idx >= count)
|
||||
return -EINVAL;
|
||||
|
||||
if (mca_funcs && mca_funcs->mca_get_mca_entry)
|
||||
return mca_funcs->mca_get_mca_entry(adev, type, idx, entry);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
return mca_funcs->mca_get_mca_entry(adev, type, idx, entry);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
|
|
@ -466,7 +466,7 @@ static int psp_sw_init(void *handle)
|
|||
}
|
||||
|
||||
ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
|
||||
amdgpu_sriov_vf(adev) ?
|
||||
(amdgpu_sriov_vf(adev) || fw_bo_location == 1) ?
|
||||
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
|
||||
&psp->fw_pri_bo,
|
||||
&psp->fw_pri_mc_addr,
|
||||
|
|
|
@ -1156,8 +1156,10 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s
|
|||
for_each_ras_error(err_node, err_data) {
|
||||
err_info = &err_node->err_info;
|
||||
|
||||
amdgpu_ras_error_statistic_ce_count(&obj->err_data, &err_info->mcm_info, err_info->ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(&obj->err_data, &err_info->mcm_info, err_info->ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(&obj->err_data,
|
||||
&err_info->mcm_info, NULL, err_info->ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(&obj->err_data,
|
||||
&err_info->mcm_info, NULL, err_info->ue_count);
|
||||
}
|
||||
} else {
|
||||
/* for legacy asic path which doesn't has error source info */
|
||||
|
@ -1174,6 +1176,9 @@ static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev,
|
|||
enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT;
|
||||
struct amdgpu_ras_block_object *block_obj = NULL;
|
||||
|
||||
if (blk == AMDGPU_RAS_BLOCK_COUNT)
|
||||
return -EINVAL;
|
||||
|
||||
if (error_query_mode == AMDGPU_RAS_INVALID_ERROR_QUERY)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -2538,7 +2543,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev)
|
|||
return 0;
|
||||
|
||||
data = &con->eh_data;
|
||||
*data = kmalloc(sizeof(**data), GFP_KERNEL | __GFP_ZERO);
|
||||
*data = kzalloc(sizeof(**data), GFP_KERNEL);
|
||||
if (!*data) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -2825,10 +2830,10 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
|||
if (con)
|
||||
return 0;
|
||||
|
||||
con = kmalloc(sizeof(struct amdgpu_ras) +
|
||||
con = kzalloc(sizeof(*con) +
|
||||
sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT +
|
||||
sizeof(struct ras_manager) * AMDGPU_RAS_MCA_BLOCK_COUNT,
|
||||
GFP_KERNEL|__GFP_ZERO);
|
||||
GFP_KERNEL);
|
||||
if (!con)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -3133,8 +3138,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* enable MCA debug on APU device */
|
||||
amdgpu_ras_set_mca_debug_mode(adev, !!(adev->flags & AMD_IS_APU));
|
||||
amdgpu_ras_set_mca_debug_mode(adev, false);
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &adev->ras_list, node) {
|
||||
if (!node->ras_obj) {
|
||||
|
@ -3691,7 +3695,8 @@ static int ras_err_info_cmp(void *priv, const struct list_head *a, const struct
|
|||
}
|
||||
|
||||
static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr)
|
||||
{
|
||||
struct ras_err_node *err_node;
|
||||
|
||||
|
@ -3705,6 +3710,9 @@ static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_d
|
|||
|
||||
memcpy(&err_node->err_info.mcm_info, mcm_info, sizeof(*mcm_info));
|
||||
|
||||
if (err_addr)
|
||||
memcpy(&err_node->err_info.err_addr, err_addr, sizeof(*err_addr));
|
||||
|
||||
err_data->err_list_count++;
|
||||
list_add_tail(&err_node->node, &err_data->err_node_list);
|
||||
list_sort(NULL, &err_data->err_node_list, ras_err_info_cmp);
|
||||
|
@ -3713,7 +3721,8 @@ static struct ras_err_info *amdgpu_ras_error_get_info(struct ras_err_data *err_d
|
|||
}
|
||||
|
||||
int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count)
|
||||
{
|
||||
struct ras_err_info *err_info;
|
||||
|
||||
|
@ -3723,7 +3732,7 @@ int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
|||
if (!count)
|
||||
return 0;
|
||||
|
||||
err_info = amdgpu_ras_error_get_info(err_data, mcm_info);
|
||||
err_info = amdgpu_ras_error_get_info(err_data, mcm_info, err_addr);
|
||||
if (!err_info)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -3734,7 +3743,8 @@ int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
|||
}
|
||||
|
||||
int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count)
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count)
|
||||
{
|
||||
struct ras_err_info *err_info;
|
||||
|
||||
|
@ -3744,7 +3754,7 @@ int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
|||
if (!count)
|
||||
return 0;
|
||||
|
||||
err_info = amdgpu_ras_error_get_info(err_data, mcm_info);
|
||||
err_info = amdgpu_ras_error_get_info(err_data, mcm_info, err_addr);
|
||||
if (!err_info)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -452,10 +452,17 @@ struct ras_fs_data {
|
|||
char debugfs_name[32];
|
||||
};
|
||||
|
||||
struct ras_err_addr {
|
||||
uint64_t err_status;
|
||||
uint64_t err_ipid;
|
||||
uint64_t err_addr;
|
||||
};
|
||||
|
||||
struct ras_err_info {
|
||||
struct amdgpu_smuio_mcm_config_info mcm_info;
|
||||
u64 ce_count;
|
||||
u64 ue_count;
|
||||
struct ras_err_addr err_addr;
|
||||
};
|
||||
|
||||
struct ras_err_node {
|
||||
|
@ -806,8 +813,10 @@ void amdgpu_ras_inst_reset_ras_error_count(struct amdgpu_device *adev,
|
|||
int amdgpu_ras_error_data_init(struct ras_err_data *err_data);
|
||||
void amdgpu_ras_error_data_fini(struct ras_err_data *err_data);
|
||||
int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count);
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count);
|
||||
int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data,
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count);
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info,
|
||||
struct ras_err_addr *err_addr, u64 count);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -531,13 +531,12 @@ int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
|
|||
if (version_major == 2 && version_minor == 1)
|
||||
adev->gfx.rlc.is_rlc_v2_1 = true;
|
||||
|
||||
if (version_minor >= 0) {
|
||||
err = amdgpu_gfx_rlc_init_microcode_v2_0(adev);
|
||||
if (err) {
|
||||
dev_err(adev->dev, "fail to init rlc v2_0 microcode\n");
|
||||
return err;
|
||||
}
|
||||
err = amdgpu_gfx_rlc_init_microcode_v2_0(adev);
|
||||
if (err) {
|
||||
dev_err(adev->dev, "fail to init rlc v2_0 microcode\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (version_minor >= 1)
|
||||
amdgpu_gfx_rlc_init_microcode_v2_1(adev);
|
||||
if (version_minor >= 2)
|
||||
|
|
|
@ -191,7 +191,8 @@ static bool amdgpu_sync_test_fence(struct amdgpu_device *adev,
|
|||
|
||||
/* Never sync to VM updates either. */
|
||||
if (fence_owner == AMDGPU_FENCE_OWNER_VM &&
|
||||
owner != AMDGPU_FENCE_OWNER_UNDEFINED)
|
||||
owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
|
||||
owner != AMDGPU_FENCE_OWNER_KFD)
|
||||
return false;
|
||||
|
||||
/* Ignore fences depending on the sync mode */
|
||||
|
|
|
@ -1062,7 +1062,8 @@ int amdgpu_ucode_create_bo(struct amdgpu_device *adev)
|
|||
{
|
||||
if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT) {
|
||||
amdgpu_bo_create_kernel(adev, adev->firmware.fw_size, PAGE_SIZE,
|
||||
amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
|
||||
(amdgpu_sriov_vf(adev) || fw_bo_location == 1) ?
|
||||
AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
|
||||
&adev->firmware.fw_buf,
|
||||
&adev->firmware.fw_buf_mc,
|
||||
&adev->firmware.fw_buf_ptr);
|
||||
|
@ -1397,9 +1398,13 @@ int amdgpu_ucode_request(struct amdgpu_device *adev, const struct firmware **fw,
|
|||
|
||||
if (err)
|
||||
return -ENODEV;
|
||||
|
||||
err = amdgpu_ucode_validate(*fw);
|
||||
if (err)
|
||||
if (err) {
|
||||
dev_dbg(adev->dev, "\"%s\" failed to validate\n", fw_name);
|
||||
release_firmware(*fw);
|
||||
*fw = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -285,6 +285,7 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
|
|||
list_for_each_entry_safe(vm_bo, tmp, &vm->idle, vm_status) {
|
||||
struct amdgpu_bo *bo = vm_bo->bo;
|
||||
|
||||
vm_bo->moved = true;
|
||||
if (!bo || bo->tbo.type != ttm_bo_type_kernel)
|
||||
list_move(&vm_bo->vm_status, &vm_bo->vm->moved);
|
||||
else if (bo->parent)
|
||||
|
|
|
@ -1313,10 +1313,10 @@ static void __xgmi_v6_4_0_query_error_count(struct amdgpu_device *adev, struct a
|
|||
|
||||
switch (xgmi_v6_4_0_pcs_mca_get_error_type(adev, status)) {
|
||||
case AMDGPU_MCA_ERROR_TYPE_UE:
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, 1ULL);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, mcm_info, NULL, 1ULL);
|
||||
break;
|
||||
case AMDGPU_MCA_ERROR_TYPE_CE:
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, 1ULL);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, mcm_info, NULL, 1ULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -395,7 +395,6 @@ static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr)
|
|||
(*ptr)++;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4474,11 +4474,43 @@ static int gfx_v11_0_wait_for_idle(void *handle)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_request_gfx_index_mutex(struct amdgpu_device *adev,
|
||||
int req)
|
||||
{
|
||||
u32 i, tmp, val;
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
/* Request with MeId=2, PipeId=0 */
|
||||
tmp = REG_SET_FIELD(0, CP_GFX_INDEX_MUTEX, REQUEST, req);
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX, CLIENTID, 4);
|
||||
WREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX, tmp);
|
||||
|
||||
val = RREG32_SOC15(GC, 0, regCP_GFX_INDEX_MUTEX);
|
||||
if (req) {
|
||||
if (val == tmp)
|
||||
break;
|
||||
} else {
|
||||
tmp = REG_SET_FIELD(tmp, CP_GFX_INDEX_MUTEX,
|
||||
REQUEST, 1);
|
||||
|
||||
/* unlocked or locked by firmware */
|
||||
if (val != tmp)
|
||||
break;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_soft_reset(void *handle)
|
||||
{
|
||||
u32 grbm_soft_reset = 0;
|
||||
u32 tmp;
|
||||
int i, j, k;
|
||||
int r, i, j, k;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
tmp = RREG32_SOC15(GC, 0, regCP_INT_CNTL);
|
||||
|
@ -4518,6 +4550,13 @@ static int gfx_v11_0_soft_reset(void *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/* Try to acquire the gfx mutex before access to CP_VMID_RESET */
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, 1);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to acquire the gfx mutex during soft reset\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
WREG32_SOC15(GC, 0, regCP_VMID_RESET, 0xfffffffe);
|
||||
|
||||
// Read CP_VMID_RESET register three times.
|
||||
|
@ -4526,6 +4565,13 @@ static int gfx_v11_0_soft_reset(void *handle)
|
|||
RREG32_SOC15(GC, 0, regCP_VMID_RESET);
|
||||
RREG32_SOC15(GC, 0, regCP_VMID_RESET);
|
||||
|
||||
/* release the gfx mutex */
|
||||
r = gfx_v11_0_request_gfx_index_mutex(adev, 0);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to release the gfx mutex during soft reset\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
if (!RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) &&
|
||||
!RREG32_SOC15(GC, 0, regCP_GFX_HQD_ACTIVE))
|
||||
|
|
|
@ -3828,8 +3828,8 @@ static void gfx_v9_4_3_inst_query_ras_err_count(struct amdgpu_device *adev,
|
|||
/* the caller should make sure initialize value of
|
||||
* err_data->ue_count and err_data->ce_count
|
||||
*/
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count);
|
||||
}
|
||||
|
||||
static void gfx_v9_4_3_inst_reset_ras_err_count(struct amdgpu_device *adev,
|
||||
|
|
|
@ -102,7 +102,9 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
|||
WREG32_SOC15_RLC(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the
|
||||
* vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
|
||||
|
|
|
@ -139,7 +139,9 @@ gfxhub_v1_2_xcc_init_system_aperture_regs(struct amdgpu_device *adev,
|
|||
WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the
|
||||
* vram which is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR.
|
||||
|
|
|
@ -1041,6 +1041,10 @@ static int gmc_v10_0_hw_fini(void *handle)
|
|||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -941,6 +941,11 @@ static int gmc_v11_0_hw_fini(void *handle)
|
|||
}
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
gmc_v11_0_gart_disable(adev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -2380,6 +2380,10 @@ static int gmc_v9_0_hw_fini(void *handle)
|
|||
|
||||
amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
|
||||
|
||||
if (adev->gmc.ecc_irq.funcs &&
|
||||
amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC))
|
||||
amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,9 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
|
|||
WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
|
||||
min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
|
||||
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
|
|
@ -652,8 +652,8 @@ static void mmhub_v1_8_inst_query_ras_error_count(struct amdgpu_device *adev,
|
|||
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
&ue_count);
|
||||
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
}
|
||||
|
||||
static void mmhub_v1_8_query_ras_error_count(struct amdgpu_device *adev,
|
||||
|
|
|
@ -2156,7 +2156,7 @@ static void sdma_v4_4_2_inst_query_ras_error_count(struct amdgpu_device *adev,
|
|||
AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE,
|
||||
&ue_count);
|
||||
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
}
|
||||
|
||||
static void sdma_v4_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "amdgpu.h"
|
||||
#include "umc/umc_12_0_0_offset.h"
|
||||
#include "umc/umc_12_0_0_sh_mask.h"
|
||||
#include "mp/mp_13_0_6_sh_mask.h"
|
||||
|
||||
const uint32_t
|
||||
umc_v12_0_channel_idx_tbl[]
|
||||
|
@ -88,16 +89,26 @@ static void umc_v12_0_reset_error_count(struct amdgpu_device *adev)
|
|||
umc_v12_0_reset_error_count_per_channel, NULL);
|
||||
}
|
||||
|
||||
bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
|
||||
bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status)
|
||||
{
|
||||
if (amdgpu_ras_is_poison_mode_supported(adev) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1))
|
||||
return true;
|
||||
|
||||
return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1));
|
||||
}
|
||||
|
||||
bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status)
|
||||
bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status)
|
||||
{
|
||||
if (amdgpu_ras_is_poison_mode_supported(adev) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1))
|
||||
return false;
|
||||
|
||||
return (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1 ||
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 &&
|
||||
|
@ -105,7 +116,7 @@ bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status)
|
|||
/* Identify data parity error in replay mode */
|
||||
((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0x5 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 0xb) &&
|
||||
!(umc_v12_0_is_uncorrectable_error(mc_umc_status)))));
|
||||
!(umc_v12_0_is_uncorrectable_error(adev, mc_umc_status)))));
|
||||
}
|
||||
|
||||
static void umc_v12_0_query_correctable_error_count(struct amdgpu_device *adev,
|
||||
|
@ -124,7 +135,7 @@ static void umc_v12_0_query_correctable_error_count(struct amdgpu_device *adev,
|
|||
mc_umc_status =
|
||||
RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4);
|
||||
|
||||
if (umc_v12_0_is_correctable_error(mc_umc_status))
|
||||
if (umc_v12_0_is_correctable_error(adev, mc_umc_status))
|
||||
*error_count += 1;
|
||||
}
|
||||
|
||||
|
@ -142,7 +153,7 @@ static void umc_v12_0_query_uncorrectable_error_count(struct amdgpu_device *adev
|
|||
mc_umc_status =
|
||||
RREG64_PCIE_EXT((mc_umc_status_addr + umc_reg_offset) * 4);
|
||||
|
||||
if (umc_v12_0_is_uncorrectable_error(mc_umc_status))
|
||||
if (umc_v12_0_is_uncorrectable_error(adev, mc_umc_status))
|
||||
*error_count += 1;
|
||||
}
|
||||
|
||||
|
@ -166,8 +177,8 @@ static int umc_v12_0_query_error_count(struct amdgpu_device *adev,
|
|||
umc_v12_0_query_correctable_error_count(adev, umc_reg_offset, &ce_count);
|
||||
umc_v12_0_query_uncorrectable_error_count(adev, umc_reg_offset, &ue_count);
|
||||
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, ce_count);
|
||||
amdgpu_ras_error_statistic_ue_count(err_data, &mcm_info, NULL, ue_count);
|
||||
amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, ce_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -360,6 +371,59 @@ static int umc_v12_0_err_cnt_init_per_channel(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void umc_v12_0_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
amdgpu_mca_smu_log_ras_error(adev,
|
||||
AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_CE, ras_error_status);
|
||||
amdgpu_mca_smu_log_ras_error(adev,
|
||||
AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_UE, ras_error_status);
|
||||
}
|
||||
|
||||
static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_node *err_node;
|
||||
uint64_t mc_umc_status;
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
||||
for_each_ras_error(err_node, err_data) {
|
||||
mc_umc_status = err_node->err_info.err_addr.err_status;
|
||||
if (!mc_umc_status)
|
||||
continue;
|
||||
|
||||
if (umc_v12_0_is_uncorrectable_error(adev, mc_umc_status)) {
|
||||
uint64_t mca_addr, err_addr, mca_ipid;
|
||||
uint32_t InstanceIdLo;
|
||||
struct amdgpu_smuio_mcm_config_info *mcm_info;
|
||||
|
||||
mcm_info = &err_node->err_info.mcm_info;
|
||||
mca_addr = err_node->err_info.err_addr.err_addr;
|
||||
mca_ipid = err_node->err_info.err_addr.err_ipid;
|
||||
|
||||
err_addr = REG_GET_FIELD(mca_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
|
||||
InstanceIdLo = REG_GET_FIELD(mca_ipid, MCMP1_IPIDT0, InstanceIdLo);
|
||||
|
||||
dev_info(adev->dev, "UMC:IPID:0x%llx, aid:%d, inst:%d, ch:%d, err_addr:0x%llx\n",
|
||||
mca_ipid,
|
||||
mcm_info->die_id,
|
||||
MCA_IPID_LO_2_UMC_INST(InstanceIdLo),
|
||||
MCA_IPID_LO_2_UMC_CH(InstanceIdLo),
|
||||
err_addr);
|
||||
|
||||
umc_v12_0_convert_error_address(adev,
|
||||
err_data, err_addr,
|
||||
MCA_IPID_LO_2_UMC_CH(InstanceIdLo),
|
||||
MCA_IPID_LO_2_UMC_INST(InstanceIdLo),
|
||||
mcm_info->die_id);
|
||||
|
||||
/* Clear umc error address content */
|
||||
memset(&err_node->err_info.err_addr,
|
||||
0, sizeof(err_node->err_info.err_addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void umc_v12_0_err_cnt_init(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_umc_loop_channels(adev,
|
||||
|
@ -386,4 +450,6 @@ struct amdgpu_umc_ras umc_v12_0_ras = {
|
|||
},
|
||||
.err_cnt_init = umc_v12_0_err_cnt_init,
|
||||
.query_ras_poison_mode = umc_v12_0_query_ras_poison_mode,
|
||||
.ecc_info_query_ras_error_count = umc_v12_0_ecc_info_query_ras_error_count,
|
||||
.ecc_info_query_ras_error_address = umc_v12_0_ecc_info_query_ras_error_address,
|
||||
};
|
||||
|
|
|
@ -117,8 +117,12 @@
|
|||
(pa) |= (UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) << UMC_V12_0_PA_CH6_BIT); \
|
||||
} while (0)
|
||||
|
||||
bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status);
|
||||
bool umc_v12_0_is_correctable_error(uint64_t mc_umc_status);
|
||||
#define MCA_IPID_LO_2_UMC_CH(_ipid_lo) (((((_ipid_lo) >> 20) & 0x1) * 4) + \
|
||||
(((_ipid_lo) >> 12) & 0xF))
|
||||
#define MCA_IPID_LO_2_UMC_INST(_ipid_lo) (((_ipid_lo) >> 21) & 0x7)
|
||||
|
||||
bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status);
|
||||
bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status);
|
||||
|
||||
extern const uint32_t
|
||||
umc_v12_0_channel_idx_tbl[]
|
||||
|
|
|
@ -330,12 +330,6 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id)
|
|||
pdd->gpuvm_limit =
|
||||
pdd->dev->kfd->shared_resources.gpuvm_size - 1;
|
||||
|
||||
/* dGPUs: the reserved space for kernel
|
||||
* before SVM
|
||||
*/
|
||||
pdd->qpd.cwsr_base = SVM_CWSR_BASE;
|
||||
pdd->qpd.ib_base = SVM_IB_BASE;
|
||||
|
||||
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_VI();
|
||||
pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base);
|
||||
}
|
||||
|
@ -345,18 +339,18 @@ static void kfd_init_apertures_v9(struct kfd_process_device *pdd, uint8_t id)
|
|||
pdd->lds_base = MAKE_LDS_APP_BASE_V9();
|
||||
pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base);
|
||||
|
||||
pdd->gpuvm_base = PAGE_SIZE;
|
||||
/* Raven needs SVM to support graphic handle, etc. Leave the small
|
||||
* reserved space before SVM on Raven as well, even though we don't
|
||||
* have to.
|
||||
* Set gpuvm_base and gpuvm_limit to CANONICAL addresses so that they
|
||||
* are used in Thunk to reserve SVM.
|
||||
*/
|
||||
pdd->gpuvm_base = SVM_USER_BASE;
|
||||
pdd->gpuvm_limit =
|
||||
pdd->dev->kfd->shared_resources.gpuvm_size - 1;
|
||||
|
||||
pdd->scratch_base = MAKE_SCRATCH_APP_BASE_V9();
|
||||
pdd->scratch_limit = MAKE_SCRATCH_APP_LIMIT(pdd->scratch_base);
|
||||
|
||||
/*
|
||||
* Place TBA/TMA on opposite side of VM hole to prevent
|
||||
* stray faults from triggering SVM on these pages.
|
||||
*/
|
||||
pdd->qpd.cwsr_base = pdd->dev->kfd->shared_resources.gpuvm_size;
|
||||
}
|
||||
|
||||
int kfd_init_apertures(struct kfd_process *process)
|
||||
|
@ -413,6 +407,12 @@ int kfd_init_apertures(struct kfd_process *process)
|
|||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* dGPUs: the reserved space for kernel
|
||||
* before SVM
|
||||
*/
|
||||
pdd->qpd.cwsr_base = SVM_CWSR_BASE;
|
||||
pdd->qpd.ib_base = SVM_IB_BASE;
|
||||
}
|
||||
|
||||
dev_dbg(kfd_device, "node id %u\n", id);
|
||||
|
|
|
@ -260,19 +260,6 @@ static void svm_migrate_put_sys_page(unsigned long addr)
|
|||
put_page(page);
|
||||
}
|
||||
|
||||
static unsigned long svm_migrate_successful_pages(struct migrate_vma *migrate)
|
||||
{
|
||||
unsigned long cpages = 0;
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < migrate->npages; i++) {
|
||||
if (migrate->src[i] & MIGRATE_PFN_VALID &&
|
||||
migrate->src[i] & MIGRATE_PFN_MIGRATE)
|
||||
cpages++;
|
||||
}
|
||||
return cpages;
|
||||
}
|
||||
|
||||
static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)
|
||||
{
|
||||
unsigned long upages = 0;
|
||||
|
@ -402,6 +389,7 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
|
|||
struct dma_fence *mfence = NULL;
|
||||
struct migrate_vma migrate = { 0 };
|
||||
unsigned long cpages = 0;
|
||||
unsigned long mpages = 0;
|
||||
dma_addr_t *scratch;
|
||||
void *buf;
|
||||
int r = -ENOMEM;
|
||||
|
@ -450,12 +438,13 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
|
|||
r = svm_migrate_copy_to_vram(node, prange, &migrate, &mfence, scratch, ttm_res_offset);
|
||||
migrate_vma_pages(&migrate);
|
||||
|
||||
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
|
||||
svm_migrate_successful_pages(&migrate), cpages, migrate.npages);
|
||||
|
||||
svm_migrate_copy_done(adev, mfence);
|
||||
migrate_vma_finalize(&migrate);
|
||||
|
||||
mpages = cpages - svm_migrate_unsuccessful_pages(&migrate);
|
||||
pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
|
||||
mpages, cpages, migrate.npages);
|
||||
|
||||
kfd_smi_event_migration_end(node, p->lead_thread->pid,
|
||||
start >> PAGE_SHIFT, end >> PAGE_SHIFT,
|
||||
0, node->id, trigger);
|
||||
|
@ -465,12 +454,12 @@ svm_migrate_vma_to_vram(struct kfd_node *node, struct svm_range *prange,
|
|||
out_free:
|
||||
kvfree(buf);
|
||||
out:
|
||||
if (!r && cpages) {
|
||||
if (!r && mpages) {
|
||||
pdd = svm_range_get_pdd_by_node(prange, node);
|
||||
if (pdd)
|
||||
WRITE_ONCE(pdd->page_in, pdd->page_in + cpages);
|
||||
WRITE_ONCE(pdd->page_in, pdd->page_in + mpages);
|
||||
|
||||
return cpages;
|
||||
return mpages;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -498,7 +487,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
|||
struct vm_area_struct *vma;
|
||||
uint64_t ttm_res_offset;
|
||||
struct kfd_node *node;
|
||||
unsigned long cpages = 0;
|
||||
unsigned long mpages = 0;
|
||||
long r = 0;
|
||||
|
||||
if (start_mgr < prange->start || last_mgr > prange->last) {
|
||||
|
@ -540,15 +529,15 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
|
|||
pr_debug("failed %ld to migrate\n", r);
|
||||
break;
|
||||
} else {
|
||||
cpages += r;
|
||||
mpages += r;
|
||||
}
|
||||
ttm_res_offset += next - addr;
|
||||
addr = next;
|
||||
}
|
||||
|
||||
if (cpages) {
|
||||
if (mpages) {
|
||||
prange->actual_loc = best_loc;
|
||||
prange->vram_pages = prange->vram_pages + cpages;
|
||||
prange->vram_pages += mpages;
|
||||
} else if (!prange->actual_loc) {
|
||||
/* if no page migrated and all pages from prange are at
|
||||
* sys ram drop svm_bo got from svm_range_vram_node_new
|
||||
|
|
|
@ -970,7 +970,7 @@ struct kfd_process {
|
|||
struct work_struct debug_event_workarea;
|
||||
|
||||
/* Tracks debug per-vmid request for debug flags */
|
||||
bool dbg_flags;
|
||||
u32 dbg_flags;
|
||||
|
||||
atomic_t poison;
|
||||
/* Queues are in paused stated because we are in the process of doing a CRIU checkpoint */
|
||||
|
|
|
@ -158,13 +158,12 @@ svm_is_valid_dma_mapping_addr(struct device *dev, dma_addr_t dma_addr)
|
|||
static int
|
||||
svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
unsigned long offset, unsigned long npages,
|
||||
unsigned long *hmm_pfns, uint32_t gpuidx, uint64_t *vram_pages)
|
||||
unsigned long *hmm_pfns, uint32_t gpuidx)
|
||||
{
|
||||
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
|
||||
dma_addr_t *addr = prange->dma_addr[gpuidx];
|
||||
struct device *dev = adev->dev;
|
||||
struct page *page;
|
||||
uint64_t vram_pages_dev;
|
||||
int i, r;
|
||||
|
||||
if (!addr) {
|
||||
|
@ -174,7 +173,6 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
|||
prange->dma_addr[gpuidx] = addr;
|
||||
}
|
||||
|
||||
vram_pages_dev = 0;
|
||||
addr += offset;
|
||||
for (i = 0; i < npages; i++) {
|
||||
if (svm_is_valid_dma_mapping_addr(dev, addr[i]))
|
||||
|
@ -184,7 +182,6 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
|||
if (is_zone_device_page(page)) {
|
||||
struct amdgpu_device *bo_adev = prange->svm_bo->node->adev;
|
||||
|
||||
vram_pages_dev++;
|
||||
addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
|
||||
bo_adev->vm_manager.vram_base_offset -
|
||||
bo_adev->kfd.pgmap.range.start;
|
||||
|
@ -201,14 +198,14 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
|
|||
pr_debug_ratelimited("dma mapping 0x%llx for page addr 0x%lx\n",
|
||||
addr[i] >> PAGE_SHIFT, page_to_pfn(page));
|
||||
}
|
||||
*vram_pages = vram_pages_dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
|
||||
unsigned long offset, unsigned long npages,
|
||||
unsigned long *hmm_pfns, uint64_t *vram_pages)
|
||||
unsigned long *hmm_pfns)
|
||||
{
|
||||
struct kfd_process *p;
|
||||
uint32_t gpuidx;
|
||||
|
@ -227,7 +224,7 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
|
|||
}
|
||||
|
||||
r = svm_range_dma_map_dev(pdd->dev->adev, prange, offset, npages,
|
||||
hmm_pfns, gpuidx, vram_pages);
|
||||
hmm_pfns, gpuidx);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
|
@ -885,14 +882,29 @@ static void svm_range_debug_dump(struct svm_range_list *svms)
|
|||
|
||||
static void *
|
||||
svm_range_copy_array(void *psrc, size_t size, uint64_t num_elements,
|
||||
uint64_t offset)
|
||||
uint64_t offset, uint64_t *vram_pages)
|
||||
{
|
||||
unsigned char *src = (unsigned char *)psrc + offset;
|
||||
unsigned char *dst;
|
||||
uint64_t i;
|
||||
|
||||
dst = kvmalloc_array(num_elements, size, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
memcpy(dst, (unsigned char *)psrc + offset, num_elements * size);
|
||||
|
||||
if (!vram_pages) {
|
||||
memcpy(dst, src, num_elements * size);
|
||||
return (void *)dst;
|
||||
}
|
||||
|
||||
*vram_pages = 0;
|
||||
for (i = 0; i < num_elements; i++) {
|
||||
dma_addr_t *temp;
|
||||
temp = (dma_addr_t *)dst + i;
|
||||
*temp = *((dma_addr_t *)src + i);
|
||||
if (*temp&SVM_RANGE_VRAM_DOMAIN)
|
||||
(*vram_pages)++;
|
||||
}
|
||||
|
||||
return (void *)dst;
|
||||
}
|
||||
|
@ -906,7 +918,7 @@ svm_range_copy_dma_addrs(struct svm_range *dst, struct svm_range *src)
|
|||
if (!src->dma_addr[i])
|
||||
continue;
|
||||
dst->dma_addr[i] = svm_range_copy_array(src->dma_addr[i],
|
||||
sizeof(*src->dma_addr[i]), src->npages, 0);
|
||||
sizeof(*src->dma_addr[i]), src->npages, 0, NULL);
|
||||
if (!dst->dma_addr[i])
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -917,7 +929,7 @@ svm_range_copy_dma_addrs(struct svm_range *dst, struct svm_range *src)
|
|||
static int
|
||||
svm_range_split_array(void *ppnew, void *ppold, size_t size,
|
||||
uint64_t old_start, uint64_t old_n,
|
||||
uint64_t new_start, uint64_t new_n)
|
||||
uint64_t new_start, uint64_t new_n, uint64_t *new_vram_pages)
|
||||
{
|
||||
unsigned char *new, *old, *pold;
|
||||
uint64_t d;
|
||||
|
@ -929,11 +941,12 @@ svm_range_split_array(void *ppnew, void *ppold, size_t size,
|
|||
return 0;
|
||||
|
||||
d = (new_start - old_start) * size;
|
||||
new = svm_range_copy_array(pold, size, new_n, d);
|
||||
/* get dma addr array for new range and calculte its vram page number */
|
||||
new = svm_range_copy_array(pold, size, new_n, d, new_vram_pages);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
d = (new_start == old_start) ? new_n * size : 0;
|
||||
old = svm_range_copy_array(pold, size, old_n, d);
|
||||
old = svm_range_copy_array(pold, size, old_n, d, NULL);
|
||||
if (!old) {
|
||||
kvfree(new);
|
||||
return -ENOMEM;
|
||||
|
@ -955,10 +968,13 @@ svm_range_split_pages(struct svm_range *new, struct svm_range *old,
|
|||
for (i = 0; i < MAX_GPU_INSTANCE; i++) {
|
||||
r = svm_range_split_array(&new->dma_addr[i], &old->dma_addr[i],
|
||||
sizeof(*old->dma_addr[i]), old->start,
|
||||
npages, new->start, new->npages);
|
||||
npages, new->start, new->npages,
|
||||
old->actual_loc ? &new->vram_pages : NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (old->actual_loc)
|
||||
old->vram_pages -= new->vram_pages;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -982,11 +998,6 @@ svm_range_split_nodes(struct svm_range *new, struct svm_range *old,
|
|||
new->svm_bo = svm_range_bo_ref(old->svm_bo);
|
||||
new->ttm_res = old->ttm_res;
|
||||
|
||||
/* set new's vram_pages as old range's now, the acurate vram_pages
|
||||
* will be updated during mapping
|
||||
*/
|
||||
new->vram_pages = min(old->vram_pages, new->npages);
|
||||
|
||||
spin_lock(&new->svm_bo->list_lock);
|
||||
list_add(&new->svm_bo_list, &new->svm_bo->range_list);
|
||||
spin_unlock(&new->svm_bo->list_lock);
|
||||
|
@ -1109,7 +1120,7 @@ static int
|
|||
svm_range_split_tail(struct svm_range *prange, uint64_t new_last,
|
||||
struct list_head *insert_list, struct list_head *remap_list)
|
||||
{
|
||||
struct svm_range *tail;
|
||||
struct svm_range *tail = NULL;
|
||||
int r = svm_range_split(prange, prange->start, new_last, &tail);
|
||||
|
||||
if (!r) {
|
||||
|
@ -1124,7 +1135,7 @@ static int
|
|||
svm_range_split_head(struct svm_range *prange, uint64_t new_start,
|
||||
struct list_head *insert_list, struct list_head *remap_list)
|
||||
{
|
||||
struct svm_range *head;
|
||||
struct svm_range *head = NULL;
|
||||
int r = svm_range_split(prange, new_start, prange->last, &head);
|
||||
|
||||
if (!r) {
|
||||
|
@ -1573,7 +1584,6 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||
struct svm_validate_context *ctx;
|
||||
unsigned long start, end, addr;
|
||||
struct kfd_process *p;
|
||||
uint64_t vram_pages;
|
||||
void *owner;
|
||||
int32_t idx;
|
||||
int r = 0;
|
||||
|
@ -1648,15 +1658,13 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||
}
|
||||
}
|
||||
|
||||
vram_pages = 0;
|
||||
start = prange->start << PAGE_SHIFT;
|
||||
end = (prange->last + 1) << PAGE_SHIFT;
|
||||
start = map_start << PAGE_SHIFT;
|
||||
end = (map_last + 1) << PAGE_SHIFT;
|
||||
for (addr = start; !r && addr < end; ) {
|
||||
struct hmm_range *hmm_range;
|
||||
unsigned long map_start_vma;
|
||||
unsigned long map_last_vma;
|
||||
struct vm_area_struct *vma;
|
||||
uint64_t vram_pages_vma;
|
||||
unsigned long next = 0;
|
||||
unsigned long offset;
|
||||
unsigned long npages;
|
||||
|
@ -1683,13 +1691,11 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||
}
|
||||
|
||||
if (!r) {
|
||||
offset = (addr - start) >> PAGE_SHIFT;
|
||||
offset = (addr >> PAGE_SHIFT) - prange->start;
|
||||
r = svm_range_dma_map(prange, ctx->bitmap, offset, npages,
|
||||
hmm_range->hmm_pfns, &vram_pages_vma);
|
||||
hmm_range->hmm_pfns);
|
||||
if (r)
|
||||
pr_debug("failed %d to dma map range\n", r);
|
||||
else
|
||||
vram_pages += vram_pages_vma;
|
||||
}
|
||||
|
||||
svm_range_lock(prange);
|
||||
|
@ -1722,19 +1728,6 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
|||
addr = next;
|
||||
}
|
||||
|
||||
if (addr == end) {
|
||||
prange->vram_pages = vram_pages;
|
||||
|
||||
/* if prange does not include any vram page and it
|
||||
* has not released svm_bo drop its svm_bo reference
|
||||
* and set its actaul_loc to sys ram
|
||||
*/
|
||||
if (!vram_pages && prange->ttm_res) {
|
||||
prange->actual_loc = 0;
|
||||
svm_range_vram_node_free(prange);
|
||||
}
|
||||
}
|
||||
|
||||
svm_range_unreserve_bos(ctx);
|
||||
if (!r)
|
||||
prange->validate_timestamp = ktime_get_boottime();
|
||||
|
|
|
@ -1342,10 +1342,11 @@ static int kfd_create_indirect_link_prop(struct kfd_topology_device *kdev, int g
|
|||
num_cpu++;
|
||||
}
|
||||
|
||||
if (list_empty(&kdev->io_link_props))
|
||||
return -ENODATA;
|
||||
|
||||
gpu_link = list_first_entry(&kdev->io_link_props,
|
||||
struct kfd_iolink_properties, list);
|
||||
if (!gpu_link)
|
||||
return -ENOMEM;
|
||||
struct kfd_iolink_properties, list);
|
||||
|
||||
for (i = 0; i < num_cpu; i++) {
|
||||
/* CPU <--> GPU */
|
||||
|
@ -1423,15 +1424,17 @@ static int kfd_add_peer_prop(struct kfd_topology_device *kdev,
|
|||
peer->gpu->adev))
|
||||
return ret;
|
||||
|
||||
if (list_empty(&kdev->io_link_props))
|
||||
return -ENODATA;
|
||||
|
||||
iolink1 = list_first_entry(&kdev->io_link_props,
|
||||
struct kfd_iolink_properties, list);
|
||||
if (!iolink1)
|
||||
return -ENOMEM;
|
||||
struct kfd_iolink_properties, list);
|
||||
|
||||
if (list_empty(&peer->io_link_props))
|
||||
return -ENODATA;
|
||||
|
||||
iolink2 = list_first_entry(&peer->io_link_props,
|
||||
struct kfd_iolink_properties, list);
|
||||
if (!iolink2)
|
||||
return -ENOMEM;
|
||||
struct kfd_iolink_properties, list);
|
||||
|
||||
props = kfd_alloc_struct(props);
|
||||
if (!props)
|
||||
|
@ -1449,17 +1452,19 @@ static int kfd_add_peer_prop(struct kfd_topology_device *kdev,
|
|||
/* CPU->CPU link*/
|
||||
cpu_dev = kfd_topology_device_by_proximity_domain(iolink1->node_to);
|
||||
if (cpu_dev) {
|
||||
list_for_each_entry(iolink3, &cpu_dev->io_link_props, list)
|
||||
if (iolink3->node_to == iolink2->node_to)
|
||||
break;
|
||||
list_for_each_entry(iolink3, &cpu_dev->io_link_props, list) {
|
||||
if (iolink3->node_to != iolink2->node_to)
|
||||
continue;
|
||||
|
||||
props->weight += iolink3->weight;
|
||||
props->min_latency += iolink3->min_latency;
|
||||
props->max_latency += iolink3->max_latency;
|
||||
props->min_bandwidth = min(props->min_bandwidth,
|
||||
iolink3->min_bandwidth);
|
||||
props->max_bandwidth = min(props->max_bandwidth,
|
||||
iolink3->max_bandwidth);
|
||||
props->weight += iolink3->weight;
|
||||
props->min_latency += iolink3->min_latency;
|
||||
props->max_latency += iolink3->max_latency;
|
||||
props->min_bandwidth = min(props->min_bandwidth,
|
||||
iolink3->min_bandwidth);
|
||||
props->max_bandwidth = min(props->max_bandwidth,
|
||||
iolink3->max_bandwidth);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WARN(1, "CPU node not found");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "dc/dc_dmub_srv.h"
|
||||
#include "dc/dc_edid_parser.h"
|
||||
#include "dc/dc_stat.h"
|
||||
#include "dc/dc_state.h"
|
||||
#include "amdgpu_dm_trace.h"
|
||||
#include "dpcd_defs.h"
|
||||
#include "link/protocols/link_dpcd.h"
|
||||
|
@ -66,7 +67,6 @@
|
|||
#include "amdgpu_dm_debugfs.h"
|
||||
#endif
|
||||
#include "amdgpu_dm_psr.h"
|
||||
#include "amdgpu_dm_replay.h"
|
||||
|
||||
#include "ivsrcid/ivsrcid_vislands30.h"
|
||||
|
||||
|
@ -1294,7 +1294,9 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
/* AGP aperture is disabled */
|
||||
if (agp_bot > agp_top) {
|
||||
logical_addr_low = adev->gmc.fb_start >> 18;
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
@ -1306,7 +1308,9 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
|
|||
logical_addr_high = adev->gmc.fb_end >> 18;
|
||||
} else {
|
||||
logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18;
|
||||
if (adev->apu_flags & AMD_APU_IS_RAVEN2)
|
||||
if (adev->apu_flags & (AMD_APU_IS_RAVEN2 |
|
||||
AMD_APU_IS_RENOIR |
|
||||
AMD_APU_IS_GREEN_SARDINE))
|
||||
/*
|
||||
* Raven2 has a HW issue that it is unable to use the vram which
|
||||
* is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
|
||||
|
@ -1711,6 +1715,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0];
|
||||
init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0];
|
||||
|
||||
init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL;
|
||||
|
||||
/* Enable DWB for tested platforms only */
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0))
|
||||
init_data.num_virtual_links = 1;
|
||||
|
@ -2607,12 +2613,10 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc)
|
|||
|
||||
memset(del_streams, 0, sizeof(del_streams));
|
||||
|
||||
context = dc_create_state(dc);
|
||||
context = dc_state_create_current_copy(dc);
|
||||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
dc_resource_state_copy_construct_current(dc, context);
|
||||
|
||||
/* First remove from context all streams */
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
struct dc_stream_state *stream = context->streams[i];
|
||||
|
@ -2622,12 +2626,12 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc)
|
|||
|
||||
/* Remove all planes for removed streams and then remove the streams */
|
||||
for (i = 0; i < del_streams_count; i++) {
|
||||
if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) {
|
||||
if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = dc_remove_stream_from_ctx(dc, context, del_streams[i]);
|
||||
res = dc_state_remove_stream(dc, context, del_streams[i]);
|
||||
if (res != DC_OK)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2635,7 +2639,7 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc)
|
|||
res = dc_commit_streams(dc, context->streams, context->stream_count);
|
||||
|
||||
fail:
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
|
||||
context_alloc_fail:
|
||||
return res;
|
||||
|
@ -2662,7 +2666,7 @@ static int dm_suspend(void *handle)
|
|||
|
||||
dc_allow_idle_optimizations(adev->dm.dc, false);
|
||||
|
||||
dm->cached_dc_state = dc_copy_state(dm->dc->current_state);
|
||||
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
|
||||
|
||||
dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, false);
|
||||
|
||||
|
@ -2856,7 +2860,7 @@ static int dm_resume(void *handle)
|
|||
bool need_hotplug = false;
|
||||
|
||||
if (dm->dc->caps.ips_support) {
|
||||
dc_dmub_srv_exit_low_power_state(dm->dc);
|
||||
dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false);
|
||||
}
|
||||
|
||||
if (amdgpu_in_reset(adev)) {
|
||||
|
@ -2909,7 +2913,7 @@ static int dm_resume(void *handle)
|
|||
|
||||
dm_gpureset_toggle_interrupts(adev, dm->cached_dc_state, true);
|
||||
|
||||
dc_release_state(dm->cached_dc_state);
|
||||
dc_state_release(dm->cached_dc_state);
|
||||
dm->cached_dc_state = NULL;
|
||||
|
||||
amdgpu_dm_irq_resume_late(adev);
|
||||
|
@ -2919,10 +2923,9 @@ static int dm_resume(void *handle)
|
|||
return 0;
|
||||
}
|
||||
/* Recreate dc_state - DC invalidates it when setting power state to S3. */
|
||||
dc_release_state(dm_state->context);
|
||||
dm_state->context = dc_create_state(dm->dc);
|
||||
dc_state_release(dm_state->context);
|
||||
dm_state->context = dc_state_create(dm->dc);
|
||||
/* TODO: Remove dc_state->dccg, use dc->dccg directly. */
|
||||
dc_resource_state_construct(dm->dc, dm_state->context);
|
||||
|
||||
/* Before powering on DC we need to re-initialize DMUB. */
|
||||
dm_dmub_hw_resume(adev);
|
||||
|
@ -3998,7 +4001,7 @@ dm_atomic_duplicate_state(struct drm_private_obj *obj)
|
|||
old_state = to_dm_atomic_state(obj->state);
|
||||
|
||||
if (old_state && old_state->context)
|
||||
new_state->context = dc_copy_state(old_state->context);
|
||||
new_state->context = dc_state_create_copy(old_state->context);
|
||||
|
||||
if (!new_state->context) {
|
||||
kfree(new_state);
|
||||
|
@ -4014,7 +4017,7 @@ static void dm_atomic_destroy_state(struct drm_private_obj *obj,
|
|||
struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
|
||||
|
||||
if (dm_state && dm_state->context)
|
||||
dc_release_state(dm_state->context);
|
||||
dc_state_release(dm_state->context);
|
||||
|
||||
kfree(dm_state);
|
||||
}
|
||||
|
@ -4050,14 +4053,12 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->context = dc_create_state(adev->dm.dc);
|
||||
state->context = dc_state_create_current_copy(adev->dm.dc);
|
||||
if (!state->context) {
|
||||
kfree(state);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct_current(adev->dm.dc, state->context);
|
||||
|
||||
drm_atomic_private_obj_init(adev_to_drm(adev),
|
||||
&adev->dm.atomic_obj,
|
||||
&state->base,
|
||||
|
@ -4065,7 +4066,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
|||
|
||||
r = amdgpu_display_modeset_create_props(adev);
|
||||
if (r) {
|
||||
dc_release_state(state->context);
|
||||
dc_state_release(state->context);
|
||||
kfree(state);
|
||||
return r;
|
||||
}
|
||||
|
@ -4077,7 +4078,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
|||
|
||||
r = amdgpu_dm_audio_init(adev);
|
||||
if (r) {
|
||||
dc_release_state(state->context);
|
||||
dc_state_release(state->context);
|
||||
kfree(state);
|
||||
return r;
|
||||
}
|
||||
|
@ -4391,7 +4392,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
enum dc_connection_type new_connection_type = dc_connection_none;
|
||||
const struct dc_plane_cap *plane;
|
||||
bool psr_feature_enabled = false;
|
||||
bool replay_feature_enabled = false;
|
||||
int max_overlay = dm->dc->caps.max_slave_planes;
|
||||
|
||||
dm->display_indexes_num = dm->dc->caps.max_streams;
|
||||
|
@ -4503,20 +4503,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) {
|
||||
switch (adev->ip_versions[DCE_HWIP][0]) {
|
||||
case IP_VERSION(3, 1, 4):
|
||||
case IP_VERSION(3, 1, 5):
|
||||
case IP_VERSION(3, 1, 6):
|
||||
case IP_VERSION(3, 2, 0):
|
||||
case IP_VERSION(3, 2, 1):
|
||||
replay_feature_enabled = true;
|
||||
break;
|
||||
default:
|
||||
replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* loops over all connectors on the board */
|
||||
for (i = 0; i < link_cnt; i++) {
|
||||
struct dc_link *link = NULL;
|
||||
|
@ -4585,12 +4571,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
|||
amdgpu_dm_update_connector_after_detect(aconnector);
|
||||
setup_backlight_device(dm, aconnector);
|
||||
|
||||
/*
|
||||
* Disable psr if replay can be enabled
|
||||
*/
|
||||
if (replay_feature_enabled && amdgpu_dm_setup_replay(link, aconnector))
|
||||
psr_feature_enabled = false;
|
||||
|
||||
if (psr_feature_enabled)
|
||||
amdgpu_dm_set_psr_caps(link);
|
||||
|
||||
|
@ -6260,8 +6240,9 @@ create_stream_for_sink(struct drm_connector *connector,
|
|||
|
||||
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
|
||||
|
||||
if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) {
|
||||
else if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
|
||||
stream->signal == SIGNAL_TYPE_EDP) {
|
||||
//
|
||||
// should decide stream support vsc sdp colorimetry capability
|
||||
// before building vsc info packet
|
||||
|
@ -6277,8 +6258,9 @@ create_stream_for_sink(struct drm_connector *connector,
|
|||
if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
|
||||
tf = TRANSFER_FUNC_GAMMA_22;
|
||||
mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
|
||||
aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
|
||||
|
||||
if (stream->link->psr_settings.psr_feature_enabled)
|
||||
aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
|
||||
}
|
||||
finish:
|
||||
dc_sink_release(sink);
|
||||
|
@ -6658,7 +6640,7 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
|
|||
if (!dc_plane_state)
|
||||
goto cleanup;
|
||||
|
||||
dc_state = dc_create_state(dc);
|
||||
dc_state = dc_state_create(dc);
|
||||
if (!dc_state)
|
||||
goto cleanup;
|
||||
|
||||
|
@ -6685,9 +6667,9 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
|
|||
dc_result = dc_validate_plane(dc, dc_plane_state);
|
||||
|
||||
if (dc_result == DC_OK)
|
||||
dc_result = dc_add_stream_to_ctx(dc, dc_state, stream);
|
||||
dc_result = dc_state_add_stream(dc, dc_state, stream);
|
||||
|
||||
if (dc_result == DC_OK && !dc_add_plane_to_context(
|
||||
if (dc_result == DC_OK && !dc_state_add_plane(
|
||||
dc,
|
||||
stream,
|
||||
dc_plane_state,
|
||||
|
@ -6699,7 +6681,7 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
|
|||
|
||||
cleanup:
|
||||
if (dc_state)
|
||||
dc_release_state(dc_state);
|
||||
dc_state_release(dc_state);
|
||||
|
||||
if (dc_plane_state)
|
||||
dc_plane_state_release(dc_plane_state);
|
||||
|
@ -7007,8 +6989,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
|||
if (IS_ERR(mst_state))
|
||||
return PTR_ERR(mst_state);
|
||||
|
||||
if (!mst_state->pbn_div.full)
|
||||
mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
|
||||
mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
|
||||
|
||||
if (!state->duplicated) {
|
||||
int max_bpc = conn_state->max_requested_bpc;
|
||||
|
@ -8858,7 +8839,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
|||
dc_stream_get_status(dm_new_crtc_state->stream);
|
||||
|
||||
if (!status)
|
||||
status = dc_stream_get_status_from_state(dc_state,
|
||||
status = dc_state_get_stream_status(dc_state,
|
||||
dm_new_crtc_state->stream);
|
||||
if (!status)
|
||||
drm_err(dev,
|
||||
|
@ -9001,7 +8982,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
if (new_con_state->crtc &&
|
||||
new_con_state->crtc->state->active &&
|
||||
drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) {
|
||||
dc_dmub_srv_exit_low_power_state(dm->dc);
|
||||
dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -9783,7 +9764,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
crtc->base.id);
|
||||
|
||||
/* i.e. reset mode */
|
||||
if (dc_remove_stream_from_ctx(
|
||||
if (dc_state_remove_stream(
|
||||
dm->dc,
|
||||
dm_state->context,
|
||||
dm_old_crtc_state->stream) != DC_OK) {
|
||||
|
@ -9826,7 +9807,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
DRM_DEBUG_ATOMIC("Enabling DRM crtc: %d\n",
|
||||
crtc->base.id);
|
||||
|
||||
if (dc_add_stream_to_ctx(
|
||||
if (dc_state_add_stream(
|
||||
dm->dc,
|
||||
dm_state->context,
|
||||
dm_new_crtc_state->stream) != DC_OK) {
|
||||
|
@ -10148,7 +10129,7 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!dc_remove_plane_from_context(
|
||||
if (!dc_state_remove_plane(
|
||||
dc,
|
||||
dm_old_crtc_state->stream,
|
||||
dm_old_plane_state->dc_state,
|
||||
|
@ -10226,7 +10207,7 @@ static int dm_update_plane_state(struct dc *dc,
|
|||
* state. It'll be released when the atomic state is
|
||||
* cleaned.
|
||||
*/
|
||||
if (!dc_add_plane_to_context(
|
||||
if (!dc_state_add_plane(
|
||||
dc,
|
||||
dm_new_crtc_state->stream,
|
||||
dc_new_plane_state,
|
||||
|
@ -10772,7 +10753,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||
DRM_DEBUG_DRIVER("drm_dp_mst_atomic_check() failed\n");
|
||||
goto fail;
|
||||
}
|
||||
status = dc_validate_global_state(dc, dm_state->context, true);
|
||||
status = dc_validate_global_state(dc, dm_state->context, false);
|
||||
if (status != DC_OK) {
|
||||
DRM_DEBUG_DRIVER("DC global validation failure: %s (%d)",
|
||||
dc_status_to_str(status), status);
|
||||
|
@ -10910,7 +10891,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
|
|||
input->cea_total_length = total_length;
|
||||
memcpy(input->payload, data, length);
|
||||
|
||||
res = dm_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
|
||||
res = dc_wake_and_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
|
||||
if (!res) {
|
||||
DRM_ERROR("EDID CEA parser failed\n");
|
||||
return false;
|
||||
|
|
|
@ -747,7 +747,7 @@ enum amdgpu_transfer_function {
|
|||
AMDGPU_TRANSFER_FUNCTION_GAMMA22_INV_EOTF,
|
||||
AMDGPU_TRANSFER_FUNCTION_GAMMA24_INV_EOTF,
|
||||
AMDGPU_TRANSFER_FUNCTION_GAMMA26_INV_EOTF,
|
||||
AMDGPU_TRANSFER_FUNCTION_COUNT
|
||||
AMDGPU_TRANSFER_FUNCTION_COUNT
|
||||
};
|
||||
|
||||
struct dm_plane_state {
|
||||
|
@ -844,7 +844,7 @@ struct dm_crtc_state {
|
|||
|
||||
int abm_level;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @regamma_tf:
|
||||
*
|
||||
* Pre-defined transfer function for converting internal FB -> wire
|
||||
|
|
|
@ -85,6 +85,18 @@ void amdgpu_dm_init_color_mod(void)
|
|||
setup_x_points_distribution();
|
||||
}
|
||||
|
||||
static inline struct fixed31_32 amdgpu_dm_fixpt_from_s3132(__u64 x)
|
||||
{
|
||||
struct fixed31_32 val;
|
||||
|
||||
/* If negative, convert to 2's complement. */
|
||||
if (x & (1ULL << 63))
|
||||
x = -(x & ~(1ULL << 63));
|
||||
|
||||
val.value = x;
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef AMD_PRIVATE_COLOR
|
||||
/* Pre-defined Transfer Functions (TF)
|
||||
*
|
||||
|
@ -430,7 +442,7 @@ static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm,
|
|||
}
|
||||
|
||||
/* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */
|
||||
matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i - (i / 4)]);
|
||||
matrix[i] = amdgpu_dm_fixpt_from_s3132(ctm->matrix[i - (i / 4)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,7 +464,7 @@ static void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm,
|
|||
*/
|
||||
for (i = 0; i < 12; i++) {
|
||||
/* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */
|
||||
matrix[i] = dc_fixpt_from_s3132(ctm->matrix[i]);
|
||||
matrix[i] = amdgpu_dm_fixpt_from_s3132(ctm->matrix[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,8 +642,7 @@ static int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *f
|
|||
static enum dc_transfer_func_predefined
|
||||
amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
|
||||
{
|
||||
switch (tf)
|
||||
{
|
||||
switch (tf) {
|
||||
default:
|
||||
case AMDGPU_TRANSFER_FUNCTION_DEFAULT:
|
||||
case AMDGPU_TRANSFER_FUNCTION_IDENTITY:
|
||||
|
@ -1137,7 +1148,7 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
|
|||
uint32_t shaper_size, lut3d_size, blend_size;
|
||||
int ret;
|
||||
|
||||
dc_plane_state->hdr_mult = dc_fixpt_from_s3132(dm_plane_state->hdr_mult);
|
||||
dc_plane_state->hdr_mult = amdgpu_dm_fixpt_from_s3132(dm_plane_state->hdr_mult);
|
||||
|
||||
shaper_lut = __extract_blob_lut(dm_plane_state->shaper_lut, &shaper_size);
|
||||
shaper_size = shaper_lut != NULL ? shaper_size : 0;
|
||||
|
@ -1225,7 +1236,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
|
|||
* plane and CRTC degamma at the same time. Explicitly reject atomic
|
||||
* updates when userspace sets both plane and CRTC degamma properties.
|
||||
*/
|
||||
if (has_crtc_cm_degamma && ret != -EINVAL){
|
||||
if (has_crtc_cm_degamma && ret != -EINVAL) {
|
||||
drm_dbg_kms(crtc->base.crtc->dev,
|
||||
"doesn't support plane and CRTC degamma at the same time\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "dc.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm_psr.h"
|
||||
#include "amdgpu_dm_replay.h"
|
||||
#include "amdgpu_dm_crtc.h"
|
||||
#include "amdgpu_dm_plane.h"
|
||||
#include "amdgpu_dm_trace.h"
|
||||
|
@ -124,12 +123,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
|
|||
* fill_dc_dirty_rects().
|
||||
*/
|
||||
if (vblank_work->stream && vblank_work->stream->link) {
|
||||
/*
|
||||
* Prioritize replay, instead of psr
|
||||
*/
|
||||
if (vblank_work->stream->link->replay_settings.replay_feature_enabled)
|
||||
amdgpu_dm_replay_enable(vblank_work->stream, false);
|
||||
else if (vblank_work->enable) {
|
||||
if (vblank_work->enable) {
|
||||
if (vblank_work->stream->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 &&
|
||||
vblank_work->stream->link->psr_settings.psr_allow_active)
|
||||
amdgpu_dm_psr_disable(vblank_work->stream);
|
||||
|
@ -138,7 +132,6 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
|
|||
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
|
||||
!amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) &&
|
||||
#endif
|
||||
vblank_work->stream->link->panel_config.psr.disallow_replay &&
|
||||
vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
|
||||
amdgpu_dm_psr_enable(vblank_work->stream);
|
||||
}
|
||||
|
@ -312,7 +305,7 @@ dm_crtc_additional_color_mgmt(struct drm_crtc *crtc)
|
|||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(crtc->dev);
|
||||
|
||||
if(adev->dm.dc->caps.color.mpc.ogam_ram)
|
||||
if (adev->dm.dc->caps.color.mpc.ogam_ram)
|
||||
drm_object_attach_property(&crtc->base,
|
||||
adev->mode_info.regamma_tf_property,
|
||||
AMDGPU_TRANSFER_FUNCTION_DEFAULT);
|
||||
|
|
|
@ -2976,7 +2976,6 @@ static int dmub_trace_mask_set(void *data, u64 val)
|
|||
struct amdgpu_device *adev = data;
|
||||
struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub;
|
||||
enum dmub_gpint_command cmd;
|
||||
enum dmub_status status;
|
||||
u64 mask = 0xffff;
|
||||
u8 shift = 0;
|
||||
u32 res;
|
||||
|
@ -3003,13 +3002,7 @@ static int dmub_trace_mask_set(void *data, u64 val)
|
|||
break;
|
||||
}
|
||||
|
||||
status = dmub_srv_send_gpint_command(srv, cmd, res, 30);
|
||||
|
||||
if (status == DMUB_STATUS_TIMEOUT)
|
||||
return -ETIMEDOUT;
|
||||
else if (status == DMUB_STATUS_INVALID)
|
||||
return -EINVAL;
|
||||
else if (status != DMUB_STATUS_OK)
|
||||
if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, res, NULL, DM_DMUB_WAIT_TYPE_WAIT))
|
||||
return -EIO;
|
||||
|
||||
usleep_range(100, 1000);
|
||||
|
@ -3026,7 +3019,6 @@ static int dmub_trace_mask_show(void *data, u64 *val)
|
|||
enum dmub_gpint_command cmd = DMUB_GPINT__GET_TRACE_BUFFER_MASK_WORD0;
|
||||
struct amdgpu_device *adev = data;
|
||||
struct dmub_srv *srv = adev->dm.dc->ctx->dmub_srv->dmub;
|
||||
enum dmub_status status;
|
||||
u8 shift = 0;
|
||||
u64 raw = 0;
|
||||
u64 res = 0;
|
||||
|
@ -3036,23 +3028,12 @@ static int dmub_trace_mask_show(void *data, u64 *val)
|
|||
return -EINVAL;
|
||||
|
||||
while (i < 4) {
|
||||
status = dmub_srv_send_gpint_command(srv, cmd, 0, 30);
|
||||
uint32_t response;
|
||||
|
||||
if (status == DMUB_STATUS_OK) {
|
||||
status = dmub_srv_get_gpint_response(srv, (u32 *) &raw);
|
||||
|
||||
if (status == DMUB_STATUS_INVALID)
|
||||
return -EINVAL;
|
||||
else if (status != DMUB_STATUS_OK)
|
||||
return -EIO;
|
||||
} else if (status == DMUB_STATUS_TIMEOUT) {
|
||||
return -ETIMEDOUT;
|
||||
} else if (status == DMUB_STATUS_INVALID) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (!dc_wake_and_execute_gpint(adev->dm.dc->ctx, cmd, 0, &response, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
raw = response;
|
||||
usleep_range(100, 1000);
|
||||
|
||||
cmd++;
|
||||
|
|
|
@ -51,6 +51,9 @@ static bool link_supports_psrsu(struct dc_link *link)
|
|||
!link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)
|
||||
return false;
|
||||
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU)
|
||||
return false;
|
||||
|
||||
return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ DC_LIBS += dcn21
|
|||
DC_LIBS += dcn201
|
||||
DC_LIBS += dcn30
|
||||
DC_LIBS += dcn301
|
||||
DC_LIBS += dcn302
|
||||
DC_LIBS += dcn303
|
||||
DC_LIBS += dcn31
|
||||
DC_LIBS += dcn314
|
||||
DC_LIBS += dcn32
|
||||
|
@ -62,7 +60,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI
|
|||
include $(AMD_DC)
|
||||
|
||||
DISPLAY_CORE = dc.o dc_stat.o dc_resource.o dc_hw_sequencer.o dc_sink.o \
|
||||
dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o dc_link_exports.o
|
||||
dc_surface.o dc_debug.o dc_stream.o dc_link_enc_cfg.o dc_link_exports.o dc_state.o
|
||||
|
||||
DISPLAY_CORE += dc_vm_helper.o
|
||||
|
||||
|
|
|
@ -103,7 +103,8 @@ void convert_float_matrix(
|
|||
|
||||
static uint32_t find_gcd(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t remainder = 0;
|
||||
uint32_t remainder;
|
||||
|
||||
while (b != 0) {
|
||||
remainder = a % b;
|
||||
a = b;
|
||||
|
|
|
@ -1014,13 +1014,20 @@ static enum bp_result get_ss_info_v4_5(
|
|||
DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
|
||||
break;
|
||||
case AS_SIGNAL_TYPE_DISPLAY_PORT:
|
||||
ss_info->spread_spectrum_percentage =
|
||||
if (bp->base.integrated_info) {
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage);
|
||||
ss_info->spread_spectrum_percentage =
|
||||
bp->base.integrated_info->gpuclk_ss_percentage;
|
||||
ss_info->type.CENTER_MODE =
|
||||
bp->base.integrated_info->gpuclk_ss_type;
|
||||
} else {
|
||||
ss_info->spread_spectrum_percentage =
|
||||
disp_cntl_tbl->dp_ss_percentage;
|
||||
ss_info->spread_spectrum_range =
|
||||
ss_info->spread_spectrum_range =
|
||||
disp_cntl_tbl->dp_ss_rate_10hz * 10;
|
||||
if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
|
||||
ss_info->type.CENTER_MODE = true;
|
||||
|
||||
if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
|
||||
ss_info->type.CENTER_MODE = true;
|
||||
}
|
||||
DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
|
||||
break;
|
||||
case AS_SIGNAL_TYPE_GPU_PLL:
|
||||
|
@ -2813,6 +2820,8 @@ static enum bp_result get_integrated_info_v2_2(
|
|||
info->ma_channel_number = info_v2_2->umachannelnumber;
|
||||
info->dp_ss_control =
|
||||
le16_to_cpu(info_v2_2->reserved1);
|
||||
info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;
|
||||
info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
|
||||
info->ext_disp_conn_info.gu_id[i] =
|
||||
|
|
|
@ -123,7 +123,7 @@ static void encoder_control_dmcub(
|
|||
sizeof(cmd.digx_encoder_control.header);
|
||||
cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig;
|
||||
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result encoder_control_digx_v1_5(
|
||||
|
@ -259,7 +259,7 @@ static void transmitter_control_dmcub(
|
|||
sizeof(cmd.dig1_transmitter_control.header);
|
||||
cmd.dig1_transmitter_control.transmitter_control.dig = *dig;
|
||||
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result transmitter_control_v1_6(
|
||||
|
@ -321,7 +321,7 @@ static void transmitter_control_dmcub_v1_7(
|
|||
sizeof(cmd.dig1_transmitter_control.header);
|
||||
cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig;
|
||||
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result transmitter_control_v1_7(
|
||||
|
@ -429,7 +429,7 @@ static void set_pixel_clock_dmcub(
|
|||
sizeof(cmd.set_pixel_clock.header);
|
||||
cmd.set_pixel_clock.pixel_clock.clk = *clk;
|
||||
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result set_pixel_clock_v7(
|
||||
|
@ -796,7 +796,7 @@ static void enable_disp_power_gating_dmcub(
|
|||
sizeof(cmd.enable_disp_power_gating.header);
|
||||
cmd.enable_disp_power_gating.power_gating.pwr = *pwr;
|
||||
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result enable_disp_power_gating_v2_1(
|
||||
|
@ -1006,7 +1006,7 @@ static void enable_lvtma_control_dmcub(
|
|||
pwrseq_instance;
|
||||
cmd.lvtma_control.data.bypass_panel_control_wait =
|
||||
bypass_panel_control_wait;
|
||||
dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static enum bp_result enable_lvtma_control(
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "dc_types.h"
|
||||
#include "dccg.h"
|
||||
#include "clk_mgr_internal.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "link.h"
|
||||
|
||||
#include "dce100/dce_clk_mgr.h"
|
||||
|
@ -63,7 +64,7 @@ int clk_mgr_helper_get_active_display_cnt(
|
|||
/* Don't count SubVP phantom pipes as part of active
|
||||
* display count
|
||||
*/
|
||||
if (stream->mall_stream_config.type == SUBVP_PHANTOM)
|
||||
if (dc_state_get_stream_subvp_type(context, stream) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
|
|
@ -253,7 +253,7 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
|
||||
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
|
||||
|
|
|
@ -284,7 +284,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
|
||||
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
|
||||
|
|
|
@ -232,7 +232,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
|
||||
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
|
|
|
@ -239,7 +239,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
|
||||
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "dccg.h"
|
||||
#include "clk_mgr_internal.h"
|
||||
|
||||
#include "dcn32/dcn32_clk_mgr_smu_msg.h"
|
||||
#include "dcn20/dcn20_clk_mgr.h"
|
||||
#include "dce100/dce_clk_mgr.h"
|
||||
|
@ -34,7 +33,7 @@
|
|||
#include "core_types.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "link.h"
|
||||
|
||||
#include "dc_state_priv.h"
|
||||
#include "atomfirmware.h"
|
||||
#include "smu13_driver_if.h"
|
||||
|
||||
|
@ -458,13 +457,43 @@ static int dcn32_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dcn32_auto_dpm_test_log(struct dc_clocks *new_clocks, struct clk_mgr_internal *clk_mgr)
|
||||
static bool dcn32_check_native_scaling(struct pipe_ctx *pipe)
|
||||
{
|
||||
bool is_native_scaling = false;
|
||||
int width = pipe->plane_state->src_rect.width;
|
||||
int height = pipe->plane_state->src_rect.height;
|
||||
|
||||
if (pipe->stream->timing.h_addressable == width &&
|
||||
pipe->stream->timing.v_addressable == height &&
|
||||
pipe->plane_state->dst_rect.width == width &&
|
||||
pipe->plane_state->dst_rect.height == height)
|
||||
is_native_scaling = true;
|
||||
|
||||
return is_native_scaling;
|
||||
}
|
||||
|
||||
static void dcn32_auto_dpm_test_log(
|
||||
struct dc_clocks *new_clocks,
|
||||
struct clk_mgr_internal *clk_mgr,
|
||||
struct dc_state *context)
|
||||
{
|
||||
unsigned int dispclk_khz_reg, dppclk_khz_reg, dprefclk_khz_reg, dcfclk_khz_reg, dtbclk_khz_reg,
|
||||
fclk_khz_reg;
|
||||
fclk_khz_reg, mall_ss_size_bytes;
|
||||
int dramclk_khz_override, fclk_khz_override, num_fclk_levels;
|
||||
|
||||
msleep(5);
|
||||
struct pipe_ctx *pipe_ctx_list[MAX_PIPES];
|
||||
int active_pipe_count = 0;
|
||||
|
||||
for (int i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
|
||||
pipe_ctx_list[active_pipe_count] = pipe_ctx;
|
||||
active_pipe_count++;
|
||||
}
|
||||
}
|
||||
|
||||
mall_ss_size_bytes = context->bw_ctx.bw.dcn.mall_ss_size_bytes;
|
||||
|
||||
dispclk_khz_reg = REG_READ(CLK1_CLK0_CURRENT_CNT); // DISPCLK
|
||||
dppclk_khz_reg = REG_READ(CLK1_CLK1_CURRENT_CNT); // DPPCLK
|
||||
|
@ -494,16 +523,49 @@ static void dcn32_auto_dpm_test_log(struct dc_clocks *new_clocks, struct clk_mgr
|
|||
//
|
||||
// AutoDPMTest: clk1:%d - clk2:%d - clk3:%d - clk4:%d\n"
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if (new_clocks &&
|
||||
if (new_clocks && active_pipe_count > 0 &&
|
||||
new_clocks->dramclk_khz > 0 &&
|
||||
new_clocks->fclk_khz > 0 &&
|
||||
new_clocks->dcfclk_khz > 0 &&
|
||||
new_clocks->dppclk_khz > 0) {
|
||||
|
||||
uint32_t pix_clk_list[MAX_PIPES] = {0};
|
||||
int p_state_list[MAX_PIPES] = {0};
|
||||
int disp_src_width_list[MAX_PIPES] = {0};
|
||||
int disp_src_height_list[MAX_PIPES] = {0};
|
||||
uint64_t disp_src_refresh_list[MAX_PIPES] = {0};
|
||||
bool is_scaled_list[MAX_PIPES] = {0};
|
||||
|
||||
for (int i = 0; i < active_pipe_count; i++) {
|
||||
struct pipe_ctx *curr_pipe_ctx = pipe_ctx_list[i];
|
||||
uint64_t refresh_rate;
|
||||
|
||||
pix_clk_list[i] = curr_pipe_ctx->stream->timing.pix_clk_100hz;
|
||||
p_state_list[i] = curr_pipe_ctx->p_state_type;
|
||||
|
||||
refresh_rate = (curr_pipe_ctx->stream->timing.pix_clk_100hz * (uint64_t)100 +
|
||||
curr_pipe_ctx->stream->timing.v_total * curr_pipe_ctx->stream->timing.h_total - (uint64_t)1);
|
||||
refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.v_total);
|
||||
refresh_rate = div_u64(refresh_rate, curr_pipe_ctx->stream->timing.h_total);
|
||||
disp_src_refresh_list[i] = refresh_rate;
|
||||
|
||||
if (curr_pipe_ctx->plane_state) {
|
||||
is_scaled_list[i] = !(dcn32_check_native_scaling(curr_pipe_ctx));
|
||||
disp_src_width_list[i] = curr_pipe_ctx->plane_state->src_rect.width;
|
||||
disp_src_height_list[i] = curr_pipe_ctx->plane_state->src_rect.height;
|
||||
}
|
||||
}
|
||||
|
||||
DC_LOG_AUTO_DPM_TEST("AutoDPMTest: dramclk:%d - fclk:%d - "
|
||||
"dcfclk:%d - dppclk:%d - dispclk_hw:%d - "
|
||||
"dppclk_hw:%d - dprefclk_hw:%d - dcfclk_hw:%d - "
|
||||
"dtbclk_hw:%d - fclk_hw:%d\n",
|
||||
"dtbclk_hw:%d - fclk_hw:%d - pix_clk_0:%d - pix_clk_1:%d - "
|
||||
"pix_clk_2:%d - pix_clk_3:%d - mall_ss_size:%d - p_state_type_0:%d - "
|
||||
"p_state_type_1:%d - p_state_type_2:%d - p_state_type_3:%d - "
|
||||
"pix_width_0:%d - pix_height_0:%d - refresh_rate_0:%lld - is_scaled_0:%d - "
|
||||
"pix_width_1:%d - pix_height_1:%d - refresh_rate_1:%lld - is_scaled_1:%d - "
|
||||
"pix_width_2:%d - pix_height_2:%d - refresh_rate_2:%lld - is_scaled_2:%d - "
|
||||
"pix_width_3:%d - pix_height_3:%d - refresh_rate_3:%lld - is_scaled_3:%d - LOG_END\n",
|
||||
dramclk_khz_override,
|
||||
fclk_khz_override,
|
||||
new_clocks->dcfclk_khz,
|
||||
|
@ -513,7 +575,14 @@ static void dcn32_auto_dpm_test_log(struct dc_clocks *new_clocks, struct clk_mgr
|
|||
dprefclk_khz_reg,
|
||||
dcfclk_khz_reg,
|
||||
dtbclk_khz_reg,
|
||||
fclk_khz_reg);
|
||||
fclk_khz_reg,
|
||||
pix_clk_list[0], pix_clk_list[1], pix_clk_list[3], pix_clk_list[2],
|
||||
mall_ss_size_bytes,
|
||||
p_state_list[0], p_state_list[1], p_state_list[2], p_state_list[3],
|
||||
disp_src_width_list[0], disp_src_height_list[0], disp_src_refresh_list[0], is_scaled_list[0],
|
||||
disp_src_width_list[1], disp_src_height_list[1], disp_src_refresh_list[1], is_scaled_list[1],
|
||||
disp_src_width_list[2], disp_src_height_list[2], disp_src_refresh_list[2], is_scaled_list[2],
|
||||
disp_src_width_list[3], disp_src_height_list[3], disp_src_refresh_list[3], is_scaled_list[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,6 +755,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
/* DCCG requires KHz precision for DTBCLK */
|
||||
clk_mgr_base->clks.ref_dtbclk_khz =
|
||||
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DTBCLK, khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz));
|
||||
|
||||
dcn32_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
|
||||
}
|
||||
|
||||
|
@ -713,8 +783,8 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
dmcu->funcs->set_psr_wait_loop(dmcu,
|
||||
clk_mgr_base->clks.dispclk_khz / 1000 / 7);
|
||||
|
||||
if (dc->config.enable_auto_dpm_test_logs && safe_to_lower) {
|
||||
dcn32_auto_dpm_test_log(new_clocks, clk_mgr);
|
||||
if (dc->config.enable_auto_dpm_test_logs) {
|
||||
dcn32_auto_dpm_test_log(new_clocks, clk_mgr, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "dc_dmub_srv.h"
|
||||
#include "link.h"
|
||||
#include "logger_types.h"
|
||||
|
||||
#undef DC_LOGGER
|
||||
#define DC_LOGGER \
|
||||
clk_mgr->base.base.ctx->logger
|
||||
|
@ -342,7 +343,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
|
||||
cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
|
||||
|
@ -417,9 +418,8 @@ bool dcn35_are_clock_states_equal(struct dc_clocks *a,
|
|||
}
|
||||
|
||||
static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
|
||||
struct clk_mgr_dcn35 *clk_mgr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct clk_bw_params dcn35_bw_params = {
|
||||
|
@ -986,7 +986,6 @@ void dcn35_clk_mgr_construct(
|
|||
struct dccg *dccg)
|
||||
{
|
||||
struct dcn35_smu_dpm_clks smu_dpm_clks = { 0 };
|
||||
struct clk_log_info log_info = {0};
|
||||
clk_mgr->base.base.ctx = ctx;
|
||||
clk_mgr->base.base.funcs = &dcn35_funcs;
|
||||
|
||||
|
@ -1039,7 +1038,7 @@ void dcn35_clk_mgr_construct(
|
|||
dcn35_bw_params.wm_table = ddr5_wm_table;
|
||||
}
|
||||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
|
||||
dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
|
||||
|
||||
clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base);
|
||||
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "dce/dce_hwseq.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "dc_state.h"
|
||||
#include "dc_state_priv.h"
|
||||
|
||||
#include "gpio_service_interface.h"
|
||||
#include "clk_mgr.h"
|
||||
|
@ -409,9 +411,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
|
|||
* avoid conflicting with firmware updates.
|
||||
*/
|
||||
if (dc->ctx->dce_version > DCE_VERSION_MAX)
|
||||
if (dc->optimized_required || dc->wm_optimized_required)
|
||||
if (dc->optimized_required)
|
||||
return false;
|
||||
|
||||
if (!memcmp(&stream->adjust, adjust, sizeof(*adjust)))
|
||||
return true;
|
||||
|
||||
stream->adjust.v_total_max = adjust->v_total_max;
|
||||
stream->adjust.v_total_mid = adjust->v_total_mid;
|
||||
stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
|
||||
|
@ -519,7 +524,7 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
|
|||
cmd.secure_display.roi_info.y_end = rect->y + rect->height;
|
||||
}
|
||||
|
||||
dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -808,7 +813,7 @@ static void dc_destruct(struct dc *dc)
|
|||
link_enc_cfg_init(dc, dc->current_state);
|
||||
|
||||
if (dc->current_state) {
|
||||
dc_release_state(dc->current_state);
|
||||
dc_state_release(dc->current_state);
|
||||
dc->current_state = NULL;
|
||||
}
|
||||
|
||||
|
@ -1020,18 +1025,6 @@ static bool dc_construct(struct dc *dc,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Creation of current_state must occur after dc->dml
|
||||
* is initialized in dc_create_resource_pool because
|
||||
* on creation it copies the contents of dc->dml
|
||||
*/
|
||||
|
||||
dc->current_state = dc_create_state(dc);
|
||||
|
||||
if (!dc->current_state) {
|
||||
dm_error("%s: failed to create validate ctx\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!create_links(dc, init_params->num_virtual_links))
|
||||
goto fail;
|
||||
|
||||
|
@ -1041,7 +1034,17 @@ static bool dc_construct(struct dc *dc,
|
|||
if (!create_link_encoders(dc))
|
||||
goto fail;
|
||||
|
||||
dc_resource_state_construct(dc, dc->current_state);
|
||||
/* Creation of current_state must occur after dc->dml
|
||||
* is initialized in dc_create_resource_pool because
|
||||
* on creation it copies the contents of dc->dml
|
||||
*/
|
||||
|
||||
dc->current_state = dc_state_create(dc);
|
||||
|
||||
if (!dc->current_state) {
|
||||
dm_error("%s: failed to create validate ctx\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -1085,7 +1088,7 @@ static void apply_ctx_interdependent_lock(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
|
||||
static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
|
||||
memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color));
|
||||
|
@ -1105,9 +1108,9 @@ static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *conte
|
|||
if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
|
||||
get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
|
||||
else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP)
|
||||
get_subvp_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
|
||||
get_subvp_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
|
||||
else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH)
|
||||
get_mclk_switch_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
|
||||
get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1115,7 +1118,7 @@ static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *conte
|
|||
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
int i, j;
|
||||
struct dc_state *dangling_context = dc_create_state(dc);
|
||||
struct dc_state *dangling_context = dc_state_create_current_copy(dc);
|
||||
struct dc_state *current_ctx;
|
||||
struct pipe_ctx *pipe;
|
||||
struct timing_generator *tg;
|
||||
|
@ -1123,8 +1126,6 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
if (dangling_context == NULL)
|
||||
return;
|
||||
|
||||
dc_resource_state_copy_construct(dc->current_state, dangling_context);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct dc_stream_state *old_stream =
|
||||
dc->current_state->res_ctx.pipe_ctx[i].stream;
|
||||
|
@ -1161,6 +1162,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
}
|
||||
|
||||
if (should_disable && old_stream) {
|
||||
bool is_phantom = dc_state_get_stream_subvp_type(dc->current_state, old_stream) == SUBVP_PHANTOM;
|
||||
pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
tg = pipe->stream_res.tg;
|
||||
/* When disabling plane for a phantom pipe, we must turn on the
|
||||
|
@ -1169,22 +1171,29 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
* state that can result in underflow or hang when enabling it
|
||||
* again for different use.
|
||||
*/
|
||||
if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (is_phantom) {
|
||||
if (tg->funcs->enable_crtc) {
|
||||
int main_pipe_width, main_pipe_height;
|
||||
struct dc_stream_state *old_paired_stream = dc_state_get_paired_subvp_stream(dc->current_state, old_stream);
|
||||
|
||||
main_pipe_width = old_stream->mall_stream_config.paired_stream->dst.width;
|
||||
main_pipe_height = old_stream->mall_stream_config.paired_stream->dst.height;
|
||||
main_pipe_width = old_paired_stream->dst.width;
|
||||
main_pipe_height = old_paired_stream->dst.height;
|
||||
if (dc->hwss.blank_phantom)
|
||||
dc->hwss.blank_phantom(dc, tg, main_pipe_width, main_pipe_height);
|
||||
tg->funcs->enable_crtc(tg);
|
||||
}
|
||||
}
|
||||
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
|
||||
|
||||
if (is_phantom)
|
||||
dc_state_rem_all_phantom_planes_for_stream(dc, old_stream, dangling_context, true);
|
||||
else
|
||||
dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context);
|
||||
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
|
||||
|
||||
if (pipe->stream && pipe->plane_state)
|
||||
dc_update_viusal_confirm_color(dc, context, pipe);
|
||||
if (pipe->stream && pipe->plane_state) {
|
||||
set_p_state_switch_method(dc, context, pipe);
|
||||
dc_update_visual_confirm_color(dc, context, pipe);
|
||||
}
|
||||
|
||||
if (dc->hwss.apply_ctx_for_surface) {
|
||||
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
|
||||
|
@ -1203,7 +1212,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
* The OTG is set to disable on falling edge of VUPDATE so the plane disable
|
||||
* will still get it's double buffer update.
|
||||
*/
|
||||
if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (is_phantom) {
|
||||
if (tg->funcs->disable_phantom_crtc)
|
||||
tg->funcs->disable_phantom_crtc(tg);
|
||||
}
|
||||
|
@ -1212,7 +1221,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
|
||||
current_ctx = dc->current_state;
|
||||
dc->current_state = dangling_context;
|
||||
dc_release_state(current_ctx);
|
||||
dc_state_release(current_ctx);
|
||||
}
|
||||
|
||||
static void disable_vbios_mode_if_required(
|
||||
|
@ -1284,7 +1293,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
|
|||
int count = 0;
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (!pipe->plane_state || pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
|
||||
if (!pipe->plane_state || dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
/* Timeout 100 ms */
|
||||
|
@ -1510,7 +1519,7 @@ static void program_timing_sync(
|
|||
}
|
||||
|
||||
for (k = 0; k < group_size; k++) {
|
||||
struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);
|
||||
struct dc_stream_status *status = dc_state_get_stream_status(ctx, pipe_set[k]->stream);
|
||||
|
||||
status->timing_sync_info.group_id = num_group;
|
||||
status->timing_sync_info.group_size = group_size;
|
||||
|
@ -1555,7 +1564,7 @@ static void program_timing_sync(
|
|||
if (group_size > 1) {
|
||||
if (sync_type == TIMING_SYNCHRONIZABLE) {
|
||||
dc->hwss.enable_timing_synchronization(
|
||||
dc, group_index, group_size, pipe_set);
|
||||
dc, ctx, group_index, group_size, pipe_set);
|
||||
} else
|
||||
if (sync_type == VBLANK_SYNCHRONIZABLE) {
|
||||
dc->hwss.enable_vblanks_synchronization(
|
||||
|
@ -1837,7 +1846,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
/* Check old context for SubVP */
|
||||
subvp_prev_use |= (old_pipe->stream && old_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM);
|
||||
subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM);
|
||||
if (subvp_prev_use)
|
||||
break;
|
||||
}
|
||||
|
@ -1995,9 +2004,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|||
old_state = dc->current_state;
|
||||
dc->current_state = context;
|
||||
|
||||
dc_release_state(old_state);
|
||||
dc_state_release(old_state);
|
||||
|
||||
dc_retain_state(dc->current_state);
|
||||
dc_state_retain(dc->current_state);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -2068,12 +2077,10 @@ enum dc_status dc_commit_streams(struct dc *dc,
|
|||
if (handle_exit_odm2to1)
|
||||
res = commit_minimal_transition_state(dc, dc->current_state);
|
||||
|
||||
context = dc_create_state(dc);
|
||||
context = dc_state_create_current_copy(dc);
|
||||
if (!context)
|
||||
goto context_alloc_fail;
|
||||
|
||||
dc_resource_state_copy_construct_current(dc, context);
|
||||
|
||||
res = dc_validate_with_context(dc, set, stream_count, context, false);
|
||||
if (res != DC_OK) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
@ -2088,7 +2095,7 @@ enum dc_status dc_commit_streams(struct dc *dc,
|
|||
streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst;
|
||||
|
||||
if (dc_is_embedded_signal(streams[i]->signal)) {
|
||||
struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]);
|
||||
struct dc_stream_status *status = dc_state_get_stream_status(context, streams[i]);
|
||||
|
||||
if (dc->hwss.is_abm_supported)
|
||||
status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]);
|
||||
|
@ -2099,7 +2106,7 @@ enum dc_status dc_commit_streams(struct dc *dc,
|
|||
}
|
||||
|
||||
fail:
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
|
||||
context_alloc_fail:
|
||||
|
||||
|
@ -2153,7 +2160,7 @@ static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
|
|||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
// Don't check flip pending on phantom pipes
|
||||
if (!pipe->plane_state || (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM))
|
||||
if (!pipe->plane_state || (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM))
|
||||
continue;
|
||||
|
||||
/* Must set to false to start with, due to OR in update function */
|
||||
|
@ -2211,7 +2218,7 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
|
|||
if (context->res_ctx.pipe_ctx[i].stream == NULL ||
|
||||
context->res_ctx.pipe_ctx[i].plane_state == NULL) {
|
||||
context->res_ctx.pipe_ctx[i].pipe_idx = i;
|
||||
dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
|
||||
dc->hwss.disable_plane(dc, context, &context->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
|
||||
process_deferred_updates(dc);
|
||||
|
@ -2223,104 +2230,6 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
|
|||
}
|
||||
|
||||
dc->optimized_required = false;
|
||||
dc->wm_optimized_required = false;
|
||||
}
|
||||
|
||||
static void init_state(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
/* Each context must have their own instance of VBA and in order to
|
||||
* initialize and obtain IP and SOC the base DML instance from DC is
|
||||
* initially copied into every context
|
||||
*/
|
||||
memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
|
||||
}
|
||||
|
||||
struct dc_state *dc_create_state(struct dc *dc)
|
||||
{
|
||||
struct dc_state *context = kvzalloc(sizeof(struct dc_state),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
init_state(dc, context);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (dc->debug.using_dml2) {
|
||||
dml2_create(dc, &dc->dml2_options, &context->bw_ctx.dml2);
|
||||
}
|
||||
#endif
|
||||
kref_init(&context->refcount);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
struct dc_state *dc_copy_state(struct dc_state *src_ctx)
|
||||
{
|
||||
int i, j;
|
||||
struct dc_state *new_ctx = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
|
||||
|
||||
if (!new_ctx)
|
||||
return NULL;
|
||||
memcpy(new_ctx, src_ctx, sizeof(struct dc_state));
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (new_ctx->bw_ctx.dml2 && !dml2_create_copy(&new_ctx->bw_ctx.dml2, src_ctx->bw_ctx.dml2)) {
|
||||
dc_release_state(new_ctx);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &new_ctx->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &new_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < new_ctx->stream_count; i++) {
|
||||
dc_stream_retain(new_ctx->streams[i]);
|
||||
for (j = 0; j < new_ctx->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
new_ctx->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
kref_init(&new_ctx->refcount);
|
||||
|
||||
return new_ctx;
|
||||
}
|
||||
|
||||
void dc_retain_state(struct dc_state *context)
|
||||
{
|
||||
kref_get(&context->refcount);
|
||||
}
|
||||
|
||||
static void dc_state_free(struct kref *kref)
|
||||
{
|
||||
struct dc_state *context = container_of(kref, struct dc_state, refcount);
|
||||
dc_resource_state_destruct(context);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
dml2_destroy(context->bw_ctx.dml2);
|
||||
context->bw_ctx.dml2 = 0;
|
||||
#endif
|
||||
|
||||
kvfree(context);
|
||||
}
|
||||
|
||||
void dc_release_state(struct dc_state *context)
|
||||
{
|
||||
kref_put(&context->refcount, dc_state_free);
|
||||
}
|
||||
|
||||
bool dc_set_generic_gpio_for_stereo(bool enable,
|
||||
|
@ -2743,8 +2652,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
|
|||
} else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
|
||||
dc->optimized_required = true;
|
||||
}
|
||||
|
||||
dc->optimized_required |= dc->wm_optimized_required;
|
||||
}
|
||||
|
||||
return type;
|
||||
|
@ -2952,9 +2859,6 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
|||
if (update->vrr_active_fixed)
|
||||
stream->vrr_active_fixed = *update->vrr_active_fixed;
|
||||
|
||||
if (update->crtc_timing_adjust)
|
||||
stream->adjust = *update->crtc_timing_adjust;
|
||||
|
||||
if (update->dpms_off)
|
||||
stream->dpms_off = *update->dpms_off;
|
||||
|
||||
|
@ -2995,11 +2899,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
|||
update->dsc_config->num_slices_v != 0);
|
||||
|
||||
/* Use temporarry context for validating new DSC config */
|
||||
struct dc_state *dsc_validate_context = dc_create_state(dc);
|
||||
struct dc_state *dsc_validate_context = dc_state_create_copy(dc->current_state);
|
||||
|
||||
if (dsc_validate_context) {
|
||||
dc_resource_state_copy_construct(dc->current_state, dsc_validate_context);
|
||||
|
||||
stream->timing.dsc_cfg = *update->dsc_config;
|
||||
stream->timing.flags.DSC = enable_dsc;
|
||||
if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
|
||||
|
@ -3008,7 +2910,7 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
|||
update->dsc_config = NULL;
|
||||
}
|
||||
|
||||
dc_release_state(dsc_validate_context);
|
||||
dc_state_release(dsc_validate_context);
|
||||
} else {
|
||||
DC_ERROR("Failed to allocate new validate context for DSC change\n");
|
||||
update->dsc_config = NULL;
|
||||
|
@ -3107,30 +3009,27 @@ static bool update_planes_and_stream_state(struct dc *dc,
|
|||
new_planes[i] = srf_updates[i].surface;
|
||||
|
||||
/* initialize scratch memory for building context */
|
||||
context = dc_create_state(dc);
|
||||
context = dc_state_create_copy(dc->current_state);
|
||||
if (context == NULL) {
|
||||
DC_ERROR("Failed to allocate new validate context!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct(
|
||||
dc->current_state, context);
|
||||
|
||||
/* For each full update, remove all existing phantom pipes first.
|
||||
* Ensures that we have enough pipes for newly added MPO planes
|
||||
*/
|
||||
if (dc->res_pool->funcs->remove_phantom_pipes)
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
|
||||
/*remove old surfaces from context */
|
||||
if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
|
||||
if (!dc_state_rem_all_planes_for_stream(dc, stream, context)) {
|
||||
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* add surface to context */
|
||||
if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
|
||||
if (!dc_state_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
|
||||
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto fail;
|
||||
|
@ -3155,19 +3054,6 @@ static bool update_planes_and_stream_state(struct dc *dc,
|
|||
|
||||
if (update_type == UPDATE_TYPE_FULL) {
|
||||
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
|
||||
/* For phantom pipes we remove and create a new set of phantom pipes
|
||||
* for each full update (because we don't know if we'll need phantom
|
||||
* pipes until after the first round of validation). However, if validation
|
||||
* fails we need to keep the existing phantom pipes (because we don't update
|
||||
* the dc->current_state).
|
||||
*
|
||||
* The phantom stream/plane refcount is decremented for validation because
|
||||
* we assume it'll be removed (the free comes when the dc_state is freed),
|
||||
* but if validation fails we have to increment back the refcount so it's
|
||||
* consistent.
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state);
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto fail;
|
||||
}
|
||||
|
@ -3188,7 +3074,7 @@ static bool update_planes_and_stream_state(struct dc *dc,
|
|||
return true;
|
||||
|
||||
fail:
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -3384,7 +3270,7 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
|
|||
|
||||
update_dirty_rect->panel_inst = panel_inst;
|
||||
update_dirty_rect->pipe_idx = j;
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3486,18 +3372,24 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
{
|
||||
int i, j;
|
||||
struct pipe_ctx *top_pipe_to_program = NULL;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
dc_z10_restore(dc);
|
||||
|
||||
top_pipe_to_program = resource_get_otg_master_for_stream(
|
||||
&context->res_ctx,
|
||||
stream);
|
||||
|
||||
if (dc->debug.visual_confirm) {
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
if (!top_pipe_to_program)
|
||||
return;
|
||||
|
||||
if (pipe->stream && pipe->plane_state)
|
||||
dc_update_viusal_confirm_color(dc, context, pipe);
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->plane_state) {
|
||||
set_p_state_switch_method(dc, context, pipe);
|
||||
|
||||
if (dc->debug.visual_confirm)
|
||||
dc_update_visual_confirm_color(dc, context, pipe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3521,6 +3413,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
stream_status = dc_state_get_stream_status(context, stream);
|
||||
|
||||
build_dmub_cmd_list(dc,
|
||||
srf_updates,
|
||||
surface_count,
|
||||
|
@ -3533,7 +3427,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
context->dmub_cmd_count,
|
||||
context->block_sequence,
|
||||
&(context->block_sequence_steps),
|
||||
top_pipe_to_program);
|
||||
top_pipe_to_program,
|
||||
stream_status);
|
||||
hwss_execute_sequence(dc,
|
||||
context->block_sequence,
|
||||
context->block_sequence_steps);
|
||||
|
@ -3629,7 +3524,7 @@ static void commit_planes_for_stream(struct dc *dc,
|
|||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
// Check old context for SubVP
|
||||
subvp_prev_use |= (old_pipe->stream && old_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM);
|
||||
subvp_prev_use |= (dc_state_get_pipe_subvp_type(dc->current_state, old_pipe) == SUBVP_PHANTOM);
|
||||
if (subvp_prev_use)
|
||||
break;
|
||||
}
|
||||
|
@ -3637,19 +3532,22 @@ static void commit_planes_for_stream(struct dc *dc,
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
|
||||
subvp_curr_use = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dc->debug.visual_confirm)
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->plane_state)
|
||||
dc_update_viusal_confirm_color(dc, context, pipe);
|
||||
if (pipe->stream && pipe->plane_state) {
|
||||
set_p_state_switch_method(dc, context, pipe);
|
||||
|
||||
if (dc->debug.visual_confirm)
|
||||
dc_update_visual_confirm_color(dc, context, pipe);
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
|
||||
struct pipe_ctx *mpcc_pipe;
|
||||
|
@ -4022,7 +3920,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) {
|
||||
if (dc_state_get_pipe_subvp_type(dc->current_state, pipe) != SUBVP_NONE) {
|
||||
subvp_active = true;
|
||||
break;
|
||||
}
|
||||
|
@ -4059,7 +3957,7 @@ struct pipe_split_policy_backup {
|
|||
static void release_minimal_transition_state(struct dc *dc,
|
||||
struct dc_state *context, struct pipe_split_policy_backup *policy)
|
||||
{
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
/* restore previous pipe split and odm policy */
|
||||
if (!dc->config.is_vmin_only_asic)
|
||||
dc->debug.pipe_split_policy = policy->mpc_policy;
|
||||
|
@ -4070,7 +3968,7 @@ static void release_minimal_transition_state(struct dc *dc,
|
|||
static struct dc_state *create_minimal_transition_state(struct dc *dc,
|
||||
struct dc_state *base_context, struct pipe_split_policy_backup *policy)
|
||||
{
|
||||
struct dc_state *minimal_transition_context = dc_create_state(dc);
|
||||
struct dc_state *minimal_transition_context = NULL;
|
||||
unsigned int i, j;
|
||||
|
||||
if (!dc->config.is_vmin_only_asic) {
|
||||
|
@ -4082,7 +3980,9 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc,
|
|||
policy->subvp_policy = dc->debug.force_disable_subvp;
|
||||
dc->debug.force_disable_subvp = true;
|
||||
|
||||
dc_resource_state_copy_construct(base_context, minimal_transition_context);
|
||||
minimal_transition_context = dc_state_create_copy(base_context);
|
||||
if (!minimal_transition_context)
|
||||
return NULL;
|
||||
|
||||
/* commit minimal state */
|
||||
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
|
||||
|
@ -4114,7 +4014,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
bool success = false;
|
||||
struct dc_state *minimal_transition_context;
|
||||
struct pipe_split_policy_backup policy;
|
||||
struct mall_temp_config mall_temp_config;
|
||||
|
||||
/* commit based on new context */
|
||||
/* Since all phantom pipes are removed in full validation,
|
||||
|
@ -4123,8 +4022,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
* pipe as subvp/phantom will be cleared (dc copy constructor
|
||||
* creates a shallow copy).
|
||||
*/
|
||||
if (dc->res_pool->funcs->save_mall_state)
|
||||
dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
|
||||
minimal_transition_context = create_minimal_transition_state(dc,
|
||||
context, &policy);
|
||||
if (minimal_transition_context) {
|
||||
|
@ -4137,16 +4034,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK;
|
||||
}
|
||||
release_minimal_transition_state(dc, minimal_transition_context, &policy);
|
||||
if (dc->res_pool->funcs->restore_mall_state)
|
||||
dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
|
||||
/* If we do a minimal transition with plane removal and the context
|
||||
* has subvp we also have to retain back the phantom stream / planes
|
||||
* since the refcount is decremented as part of the min transition
|
||||
* (we commit a state with no subvp, so the phantom streams / planes
|
||||
* had to be removed).
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, context);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
@ -4214,7 +4101,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (pipe->stream && dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
|
||||
subvp_in_use = true;
|
||||
break;
|
||||
}
|
||||
|
@ -4401,8 +4288,7 @@ static bool full_update_required(struct dc *dc,
|
|||
stream_update->mst_bw_update ||
|
||||
stream_update->func_shaper ||
|
||||
stream_update->lut3d_func ||
|
||||
stream_update->pending_test_pattern ||
|
||||
stream_update->crtc_timing_adjust))
|
||||
stream_update->pending_test_pattern))
|
||||
return true;
|
||||
|
||||
if (stream) {
|
||||
|
@ -4480,7 +4366,6 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||
struct dc_state *context;
|
||||
enum surface_update_type update_type;
|
||||
int i;
|
||||
struct mall_temp_config mall_temp_config;
|
||||
struct dc_fast_update fast_update[MAX_SURFACES] = {0};
|
||||
|
||||
/* In cases where MPO and split or ODM are used transitions can
|
||||
|
@ -4524,23 +4409,10 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||
* pipe as subvp/phantom will be cleared (dc copy constructor
|
||||
* creates a shallow copy).
|
||||
*/
|
||||
if (dc->res_pool->funcs->save_mall_state)
|
||||
dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
|
||||
if (!commit_minimal_transition_state(dc, context)) {
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
return false;
|
||||
}
|
||||
if (dc->res_pool->funcs->restore_mall_state)
|
||||
dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
|
||||
|
||||
/* If we do a minimal transition with plane removal and the context
|
||||
* has subvp we also have to retain back the phantom stream / planes
|
||||
* since the refcount is decremented as part of the min transition
|
||||
* (we commit a state with no subvp, so the phantom streams / planes
|
||||
* had to be removed).
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, context);
|
||||
update_type = UPDATE_TYPE_FULL;
|
||||
}
|
||||
|
||||
|
@ -4597,7 +4469,7 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||
struct dc_state *old = dc->current_state;
|
||||
|
||||
dc->current_state = context;
|
||||
dc_release_state(old);
|
||||
dc_state_release(old);
|
||||
|
||||
// clear any forced full updates
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
|
@ -4656,14 +4528,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
if (update_type >= UPDATE_TYPE_FULL) {
|
||||
|
||||
/* initialize scratch memory for building context */
|
||||
context = dc_create_state(dc);
|
||||
context = dc_state_create_copy(state);
|
||||
if (context == NULL) {
|
||||
DC_ERROR("Failed to allocate new validate context!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct(state, context);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
@ -4702,7 +4572,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
if (update_type >= UPDATE_TYPE_FULL) {
|
||||
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
|
||||
DC_ERROR("Mode validation failed for stream update!\n");
|
||||
dc_release_state(context);
|
||||
dc_state_release(context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4735,7 +4605,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
struct dc_state *old = dc->current_state;
|
||||
|
||||
dc->current_state = context;
|
||||
dc_release_state(old);
|
||||
dc_state_release(old);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
@ -4808,7 +4678,7 @@ void dc_set_power_state(
|
|||
|
||||
switch (power_state) {
|
||||
case DC_ACPI_CM_POWER_STATE_D0:
|
||||
dc_resource_state_construct(dc, dc->current_state);
|
||||
dc_state_construct(dc, dc->current_state);
|
||||
|
||||
dc_z10_restore(dc);
|
||||
|
||||
|
@ -4823,7 +4693,7 @@ void dc_set_power_state(
|
|||
default:
|
||||
ASSERT(dc->current_state->stream_count == 0);
|
||||
|
||||
dc_resource_state_destruct(dc->current_state);
|
||||
dc_state_destruct(dc->current_state);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -4900,6 +4770,38 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* enable/disable eDP Replay without specify stream for eDP */
|
||||
bool dc_set_replay_allow_active(struct dc *dc, bool active)
|
||||
{
|
||||
int i;
|
||||
bool allow_active;
|
||||
|
||||
for (i = 0; i < dc->current_state->stream_count; i++) {
|
||||
struct dc_link *link;
|
||||
struct dc_stream_state *stream = dc->current_state->streams[i];
|
||||
|
||||
link = stream->link;
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (link->replay_settings.replay_feature_enabled) {
|
||||
if (active && !link->replay_settings.replay_allow_active) {
|
||||
allow_active = true;
|
||||
if (!dc_link_set_replay_allow_active(link, &allow_active,
|
||||
false, false, NULL))
|
||||
return false;
|
||||
} else if (!active && link->replay_settings.replay_allow_active) {
|
||||
allow_active = false;
|
||||
if (!dc_link_set_replay_allow_active(link, &allow_active,
|
||||
true, false, NULL))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dc_allow_idle_optimizations(struct dc *dc, bool allow)
|
||||
{
|
||||
if (dc->debug.disable_idle_power_optimizations)
|
||||
|
@ -5093,18 +4995,28 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc)
|
|||
*/
|
||||
bool dc_is_dmub_outbox_supported(struct dc *dc)
|
||||
{
|
||||
/* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */
|
||||
if (dc->ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
|
||||
dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 &&
|
||||
!dc->debug.dpia_debug.bits.disable_dpia)
|
||||
return true;
|
||||
switch (dc->ctx->asic_id.chip_family) {
|
||||
|
||||
if (dc->ctx->asic_id.chip_family == AMDGPU_FAMILY_GC_11_0_1 &&
|
||||
!dc->debug.dpia_debug.bits.disable_dpia)
|
||||
return true;
|
||||
case FAMILY_YELLOW_CARP:
|
||||
/* DCN31 B0 USB4 DPIA needs dmub notifications for interrupts */
|
||||
if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0 &&
|
||||
!dc->debug.dpia_debug.bits.disable_dpia)
|
||||
return true;
|
||||
break;
|
||||
|
||||
case AMDGPU_FAMILY_GC_11_0_1:
|
||||
case AMDGPU_FAMILY_GC_11_5_0:
|
||||
if (!dc->debug.dpia_debug.bits.disable_dpia)
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* dmub aux needs dmub notifications to be enabled */
|
||||
return dc->debug.enable_dmub_aux_for_legacy_ddc;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5201,7 +5113,7 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
|
|||
);
|
||||
}
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5255,7 +5167,7 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
|
|||
cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type;
|
||||
cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data;
|
||||
|
||||
if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
|
||||
if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
|
||||
/* command is not processed by dmub */
|
||||
notify->sc_status = SET_CONFIG_UNKNOWN_ERROR;
|
||||
return is_cmd_complete;
|
||||
|
@ -5298,7 +5210,7 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
|
|||
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 (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
/* command is not processed by dmub */
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
|
@ -5336,7 +5248,7 @@ void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
|
|||
cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE;
|
||||
cmd.dpia_hpd_int_enable.enable = hpd_int_enable;
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable);
|
||||
}
|
||||
|
@ -5435,6 +5347,8 @@ bool dc_abm_save_restore(
|
|||
struct dc_link *link = stream->sink->link;
|
||||
struct dc_link *edp_links[MAX_NUM_EDP];
|
||||
|
||||
if (link->replay_settings.replay_feature_enabled)
|
||||
return false;
|
||||
|
||||
/*find primary pipe associated with stream*/
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "basics/dc_common.h"
|
||||
#include "resource.h"
|
||||
#include "dc_dmub_srv.h"
|
||||
#include "dc_state_priv.h"
|
||||
|
||||
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
|
@ -425,45 +426,130 @@ void get_hdr_visual_confirm_color(
|
|||
}
|
||||
|
||||
void get_subvp_visual_confirm_color(
|
||||
struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct tg_color *color)
|
||||
{
|
||||
uint32_t color_value = MAX_TG_COLOR_VALUE;
|
||||
bool enable_subvp = false;
|
||||
int i;
|
||||
|
||||
if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->stream->mall_stream_config.paired_stream &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
/* SubVP enable - red */
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = 0;
|
||||
if (pipe_ctx) {
|
||||
switch (pipe_ctx->p_state_type) {
|
||||
case P_STATE_SUB_VP:
|
||||
color->color_r_cr = color_value;
|
||||
enable_subvp = true;
|
||||
|
||||
if (pipe_ctx->stream == pipe->stream)
|
||||
return;
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = 0;
|
||||
break;
|
||||
case P_STATE_DRR_SUB_VP:
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = color_value;
|
||||
color->color_b_cb = 0;
|
||||
break;
|
||||
case P_STATE_V_BLANK_SUB_VP:
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = color_value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
color->color_r_cr = 0;
|
||||
if (pipe_ctx->stream->allow_freesync == 1) {
|
||||
/* SubVP enable and DRR on - green */
|
||||
color->color_b_cb = 0;
|
||||
void get_mclk_switch_visual_confirm_color(
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct tg_color *color)
|
||||
{
|
||||
uint32_t color_value = MAX_TG_COLOR_VALUE;
|
||||
|
||||
if (pipe_ctx) {
|
||||
switch (pipe_ctx->p_state_type) {
|
||||
case P_STATE_V_BLANK:
|
||||
color->color_r_cr = color_value;
|
||||
color->color_g_y = color_value;
|
||||
} else {
|
||||
/* SubVP enable and No DRR - blue */
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = 0;
|
||||
break;
|
||||
case P_STATE_FPO:
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = color_value;
|
||||
color->color_b_cb = color_value;
|
||||
break;
|
||||
case P_STATE_V_ACTIVE:
|
||||
color->color_r_cr = color_value;
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = color_value;
|
||||
break;
|
||||
case P_STATE_SUB_VP:
|
||||
color->color_r_cr = color_value;
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = 0;
|
||||
break;
|
||||
case P_STATE_DRR_SUB_VP:
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = color_value;
|
||||
color->color_b_cb = 0;
|
||||
break;
|
||||
case P_STATE_V_BLANK_SUB_VP:
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = 0;
|
||||
color->color_b_cb = color_value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_p_state_switch_method(
|
||||
struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
|
||||
bool enable_subvp;
|
||||
|
||||
if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
|
||||
return;
|
||||
|
||||
if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
|
||||
dm_dram_clock_change_unsupported) {
|
||||
/* MCLK switching is supported */
|
||||
if (!pipe_ctx->has_vactive_margin) {
|
||||
/* In Vblank - yellow */
|
||||
pipe_ctx->p_state_type = P_STATE_V_BLANK;
|
||||
|
||||
if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
|
||||
/* FPO + Vblank - cyan */
|
||||
pipe_ctx->p_state_type = P_STATE_FPO;
|
||||
}
|
||||
} else {
|
||||
/* In Vactive - pink */
|
||||
pipe_ctx->p_state_type = P_STATE_V_ACTIVE;
|
||||
}
|
||||
|
||||
/* SubVP */
|
||||
enable_subvp = false;
|
||||
|
||||
for (int i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && dc_state_get_paired_subvp_stream(context, pipe->stream) &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
|
||||
/* SubVP enable - red */
|
||||
pipe_ctx->p_state_type = P_STATE_SUB_VP;
|
||||
enable_subvp = true;
|
||||
|
||||
if (pipe_ctx->stream == pipe->stream)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_subvp && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_NONE) {
|
||||
if (pipe_ctx->stream->allow_freesync == 1) {
|
||||
/* SubVP enable and DRR on - green */
|
||||
pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP;
|
||||
} else {
|
||||
/* SubVP enable and No DRR - blue */
|
||||
pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,7 +559,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
unsigned int dmub_cmd_count,
|
||||
struct block_sequence block_sequence[],
|
||||
int *num_steps,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_stream_status *stream_status)
|
||||
{
|
||||
struct dc_plane_state *plane = pipe_ctx->plane_state;
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
|
@ -490,7 +577,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
if (dc->hwss.subvp_pipe_control_lock_fast) {
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
|
||||
plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
|
||||
block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
|
||||
(*num_steps)++;
|
||||
}
|
||||
|
@ -529,7 +617,7 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
}
|
||||
if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
|
||||
if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
|
||||
current_mpc_pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
stream_status->mall_stream_config.type == SUBVP_MAIN) {
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.addr = ¤t_mpc_pipe->plane_state->address;
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
|
||||
|
@ -612,7 +700,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
if (dc->hwss.subvp_pipe_control_lock_fast) {
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
|
||||
plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
|
||||
block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
|
||||
(*num_steps)++;
|
||||
}
|
||||
|
@ -724,7 +813,7 @@ void hwss_send_dmcub_cmd(union block_sequence_params *params)
|
|||
union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd;
|
||||
enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type;
|
||||
|
||||
dm_execute_dmub_cmd(ctx, cmd, wait_type);
|
||||
dc_wake_and_execute_dmub_cmd(ctx, cmd, wait_type);
|
||||
}
|
||||
|
||||
void hwss_program_manual_trigger(union block_sequence_params *params)
|
||||
|
@ -812,42 +901,6 @@ void hwss_subvp_save_surf_addr(union block_sequence_params *params)
|
|||
dc_dmub_srv_subvp_save_surf_addr(dc_dmub_srv, addr, subvp_index);
|
||||
}
|
||||
|
||||
void get_mclk_switch_visual_confirm_color(
|
||||
struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct tg_color *color)
|
||||
{
|
||||
uint32_t color_value = MAX_TG_COLOR_VALUE;
|
||||
struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
|
||||
|
||||
if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
|
||||
return;
|
||||
|
||||
if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
|
||||
dm_dram_clock_change_unsupported) {
|
||||
/* MCLK switching is supported */
|
||||
if (!pipe_ctx->has_vactive_margin) {
|
||||
/* In Vblank - yellow */
|
||||
color->color_r_cr = color_value;
|
||||
color->color_g_y = color_value;
|
||||
|
||||
if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
|
||||
/* FPO + Vblank - cyan */
|
||||
color->color_r_cr = 0;
|
||||
color->color_g_y = color_value;
|
||||
color->color_b_cb = color_value;
|
||||
}
|
||||
} else {
|
||||
/* In Vactive - pink */
|
||||
color->color_r_cr = color_value;
|
||||
color->color_b_cb = color_value;
|
||||
}
|
||||
/* SubVP */
|
||||
get_subvp_visual_confirm_color(dc, context, pipe_ctx, color);
|
||||
}
|
||||
}
|
||||
|
||||
void get_surface_tile_visual_confirm_color(
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct tg_color *color)
|
||||
|
|
|
@ -467,6 +467,13 @@ bool dc_link_setup_psr(struct dc_link *link,
|
|||
return link->dc->link_srv->edp_setup_psr(link, stream, psr_config, psr_context);
|
||||
}
|
||||
|
||||
bool dc_link_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
|
||||
bool wait, bool force_static, const unsigned int *power_opts)
|
||||
{
|
||||
return link->dc->link_srv->edp_set_replay_allow_active(link, allow_active, wait,
|
||||
force_static, power_opts);
|
||||
}
|
||||
|
||||
bool dc_link_get_replay_state(const struct dc_link *link, uint64_t *state)
|
||||
{
|
||||
return link->dc->link_srv->edp_get_replay_state(link, state);
|
||||
|
@ -497,7 +504,7 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable)
|
|||
link->dc->link_srv->enable_hpd_filter(link, enable);
|
||||
}
|
||||
|
||||
bool dc_link_validate(struct dc *dc, const struct dc_stream_state *streams, const unsigned int count)
|
||||
bool dc_link_dp_dpia_validate(struct dc *dc, const struct dc_stream_state *streams, const unsigned int count)
|
||||
{
|
||||
return dc->link_srv->validate_dpia_bandwidth(streams, count);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "link_enc_cfg.h"
|
||||
#include "link.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "virtual/virtual_link_hwss.h"
|
||||
#include "link/hwss/link_hwss_dio.h"
|
||||
#include "link/hwss/link_hwss_dpia.h"
|
||||
|
@ -2459,6 +2460,9 @@ void resource_remove_otg_master_for_stream_output(struct dc_state *context,
|
|||
struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(
|
||||
&context->res_ctx, stream);
|
||||
|
||||
if (!otg_master)
|
||||
return;
|
||||
|
||||
ASSERT(resource_get_odm_slice_count(otg_master) == 1);
|
||||
ASSERT(otg_master->plane_state == NULL);
|
||||
ASSERT(otg_master->stream_res.stream_enc);
|
||||
|
@ -2993,189 +2997,6 @@ bool resource_update_pipes_for_plane_with_slice_count(
|
|||
return result;
|
||||
}
|
||||
|
||||
bool dc_add_plane_to_context(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context)
|
||||
{
|
||||
struct resource_pool *pool = dc->res_pool;
|
||||
struct pipe_ctx *otg_master_pipe;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
bool added = false;
|
||||
|
||||
stream_status = dc_stream_get_status_from_state(context, stream);
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream not found; failed to attach surface!\n");
|
||||
goto out;
|
||||
} else if (stream_status->plane_count == MAX_SURFACE_NUM) {
|
||||
dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
|
||||
plane_state, MAX_SURFACE_NUM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
otg_master_pipe = resource_get_otg_master_for_stream(
|
||||
&context->res_ctx, stream);
|
||||
added = resource_append_dpp_pipes_for_plane_composition(context,
|
||||
dc->current_state, pool, otg_master_pipe, plane_state);
|
||||
|
||||
if (added) {
|
||||
stream_status->plane_states[stream_status->plane_count] =
|
||||
plane_state;
|
||||
stream_status->plane_count++;
|
||||
dc_plane_state_retain(plane_state);
|
||||
}
|
||||
|
||||
out:
|
||||
return added;
|
||||
}
|
||||
|
||||
bool dc_remove_plane_from_context(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct resource_pool *pool = dc->res_pool;
|
||||
|
||||
if (!plane_state)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++)
|
||||
if (context->streams[i] == stream) {
|
||||
stream_status = &context->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream not found; failed to remove plane.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
resource_remove_dpp_pipes_for_plane_composition(
|
||||
context, pool, plane_state);
|
||||
|
||||
for (i = 0; i < stream_status->plane_count; i++) {
|
||||
if (stream_status->plane_states[i] == plane_state) {
|
||||
dc_plane_state_release(stream_status->plane_states[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == stream_status->plane_count) {
|
||||
dm_error("Existing plane_state not found; failed to detach it!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
stream_status->plane_count--;
|
||||
|
||||
/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
|
||||
for (; i < stream_status->plane_count; i++)
|
||||
stream_status->plane_states[i] = stream_status->plane_states[i + 1];
|
||||
|
||||
stream_status->plane_states[stream_status->plane_count] = NULL;
|
||||
|
||||
if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
|
||||
/* ODM combine could prevent us from supporting more planes
|
||||
* we will reset ODM slice count back to 1 when all planes have
|
||||
* been removed to maximize the amount of planes supported when
|
||||
* new planes are added.
|
||||
*/
|
||||
resource_update_pipes_for_stream_with_slice_count(
|
||||
context, dc->current_state, dc->res_pool, stream, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_rem_all_planes_for_stream - Remove planes attached to the target stream.
|
||||
*
|
||||
* @dc: Current dc state.
|
||||
* @stream: Target stream, which we want to remove the attached plans.
|
||||
* @context: New context.
|
||||
*
|
||||
* Return:
|
||||
* Return true if DC was able to remove all planes from the target
|
||||
* stream, otherwise, return false.
|
||||
*/
|
||||
bool dc_rem_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i, old_plane_count;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
|
||||
|
||||
for (i = 0; i < context->stream_count; i++)
|
||||
if (context->streams[i] == stream) {
|
||||
stream_status = &context->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream %p not found!\n", stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
old_plane_count = stream_status->plane_count;
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
del_planes[i] = stream_status->plane_states[i];
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
const struct dc_validation_set set[],
|
||||
int set_count,
|
||||
struct dc_state *context)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < set_count; i++)
|
||||
if (set[i].stream == stream)
|
||||
break;
|
||||
|
||||
if (i == set_count) {
|
||||
dm_error("Stream %p not found in set!\n", stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (j = 0; j < set[i].plane_count; j++)
|
||||
if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state * const *plane_states,
|
||||
int plane_count,
|
||||
struct dc_state *context)
|
||||
{
|
||||
struct dc_validation_set set;
|
||||
int i;
|
||||
|
||||
set.stream = stream;
|
||||
set.plane_count = plane_count;
|
||||
|
||||
for (i = 0; i < plane_count; i++)
|
||||
set.plane_states[i] = plane_states[i];
|
||||
|
||||
return add_all_planes_for_stream(dc, stream, &set, 1, context);
|
||||
}
|
||||
|
||||
bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
|
||||
struct dc_stream_state *new_stream)
|
||||
{
|
||||
|
@ -3327,84 +3148,6 @@ static struct audio *find_first_free_audio(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state.
|
||||
*/
|
||||
enum dc_status dc_add_stream_to_ctx(
|
||||
struct dc *dc,
|
||||
struct dc_state *new_ctx,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
enum dc_status res;
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) {
|
||||
DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
new_ctx->streams[new_ctx->stream_count] = stream;
|
||||
dc_stream_retain(stream);
|
||||
new_ctx->stream_count++;
|
||||
|
||||
res = resource_add_otg_master_for_stream_output(
|
||||
new_ctx, dc->res_pool, stream);
|
||||
if (res != DC_OK)
|
||||
DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* dc_remove_stream_from_ctx() - Remove a stream from a dc_state.
|
||||
*/
|
||||
enum dc_status dc_remove_stream_from_ctx(
|
||||
struct dc *dc,
|
||||
struct dc_state *new_ctx,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
int i;
|
||||
struct dc_context *dc_ctx = dc->ctx;
|
||||
struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream(
|
||||
&new_ctx->res_ctx, stream);
|
||||
|
||||
if (!del_pipe) {
|
||||
DC_ERROR("Pipe not found for stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
resource_update_pipes_for_stream_with_slice_count(new_ctx,
|
||||
dc->current_state, dc->res_pool, stream, 1);
|
||||
resource_remove_otg_master_for_stream_output(
|
||||
new_ctx, dc->res_pool, stream);
|
||||
|
||||
for (i = 0; i < new_ctx->stream_count; i++)
|
||||
if (new_ctx->streams[i] == stream)
|
||||
break;
|
||||
|
||||
if (new_ctx->streams[i] != stream) {
|
||||
DC_ERROR("Context doesn't have stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
dc_stream_release(new_ctx->streams[i]);
|
||||
new_ctx->stream_count--;
|
||||
|
||||
/* Trim back arrays */
|
||||
for (; i < new_ctx->stream_count; i++) {
|
||||
new_ctx->streams[i] = new_ctx->streams[i + 1];
|
||||
new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
|
||||
}
|
||||
|
||||
new_ctx->streams[new_ctx->stream_count] = NULL;
|
||||
memset(
|
||||
&new_ctx->stream_status[new_ctx->stream_count],
|
||||
0,
|
||||
sizeof(new_ctx->stream_status[0]));
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
static struct dc_stream_state *find_pll_sharable_stream(
|
||||
struct dc_stream_state *stream_needs_pll,
|
||||
struct dc_state *context)
|
||||
|
@ -3784,34 +3527,6 @@ enum dc_status resource_map_pool_resources(
|
|||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
|
||||
*
|
||||
* @dc: copy out of dc->current_state
|
||||
* @dst_ctx: copy into this
|
||||
*
|
||||
* This function makes a shallow copy of the current DC state and increments
|
||||
* refcounts on existing streams and planes.
|
||||
*/
|
||||
void dc_resource_state_copy_construct_current(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
dc_resource_state_copy_construct(dc->current_state, dst_ctx);
|
||||
}
|
||||
|
||||
|
||||
void dc_resource_state_construct(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
dst_ctx->clk_mgr = dc->clk_mgr;
|
||||
|
||||
/* Initialise DIG link encoder resource tracking variables. */
|
||||
link_enc_cfg_init(dc, dst_ctx);
|
||||
}
|
||||
|
||||
|
||||
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
|
||||
{
|
||||
if (dc->res_pool == NULL)
|
||||
|
@ -3855,6 +3570,31 @@ static bool planes_changed_for_existing_stream(struct dc_state *context,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
const struct dc_validation_set set[],
|
||||
int set_count,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < set_count; i++)
|
||||
if (set[i].stream == stream)
|
||||
break;
|
||||
|
||||
if (i == set_count) {
|
||||
dm_error("Stream %p not found in set!\n", stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (j = 0; j < set[i].plane_count; j++)
|
||||
if (!dc_state_add_plane(dc, stream, set[i].plane_states[j], state))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_validate_with_context - Validate and update the potential new stream in the context object
|
||||
*
|
||||
|
@ -3960,7 +3700,8 @@ enum dc_status dc_validate_with_context(struct dc *dc,
|
|||
unchanged_streams[i],
|
||||
set,
|
||||
set_count)) {
|
||||
if (!dc_rem_all_planes_for_stream(dc,
|
||||
|
||||
if (!dc_state_rem_all_planes_for_stream(dc,
|
||||
unchanged_streams[i],
|
||||
context)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
|
@ -3982,12 +3723,24 @@ enum dc_status dc_validate_with_context(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
if (dc_state_get_stream_subvp_type(context, del_streams[i]) == SUBVP_PHANTOM) {
|
||||
/* remove phantoms specifically */
|
||||
if (!dc_state_rem_all_phantom_planes_for_stream(dc, del_streams[i], context, true)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = dc_state_remove_phantom_stream(dc, context, del_streams[i]);
|
||||
dc_state_release_phantom_stream(dc, context, del_streams[i]);
|
||||
} else {
|
||||
if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = dc_state_remove_stream(dc, context, del_streams[i]);
|
||||
}
|
||||
|
||||
res = dc_remove_stream_from_ctx(dc, context, del_streams[i]);
|
||||
if (res != DC_OK)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -4010,7 +3763,7 @@ enum dc_status dc_validate_with_context(struct dc *dc,
|
|||
/* Add new streams and then add all planes for the new stream */
|
||||
for (i = 0; i < add_streams_count; i++) {
|
||||
calculate_phy_pix_clks(add_streams[i]);
|
||||
res = dc_add_stream_to_ctx(dc, context, add_streams[i]);
|
||||
res = dc_state_add_stream(dc, context, add_streams[i]);
|
||||
if (res != DC_OK)
|
||||
goto fail;
|
||||
|
||||
|
@ -4516,84 +4269,6 @@ static void set_vtem_info_packet(
|
|||
*info_packet = stream->vtem_infopacket;
|
||||
}
|
||||
|
||||
void dc_resource_state_destruct(struct dc_state *context)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_release(
|
||||
context->stream_status[i].plane_states[j]);
|
||||
|
||||
context->stream_status[i].plane_count = 0;
|
||||
dc_stream_release(context->streams[i]);
|
||||
context->streams[i] = NULL;
|
||||
}
|
||||
context->stream_count = 0;
|
||||
context->stream_mask = 0;
|
||||
memset(&context->res_ctx, 0, sizeof(context->res_ctx));
|
||||
memset(&context->pp_display_cfg, 0, sizeof(context->pp_display_cfg));
|
||||
memset(&context->dcn_bw_vars, 0, sizeof(context->dcn_bw_vars));
|
||||
context->clk_mgr = NULL;
|
||||
memset(&context->bw_ctx.bw, 0, sizeof(context->bw_ctx.bw));
|
||||
memset(context->block_sequence, 0, sizeof(context->block_sequence));
|
||||
context->block_sequence_steps = 0;
|
||||
memset(context->dc_dmub_cmd, 0, sizeof(context->dc_dmub_cmd));
|
||||
context->dmub_cmd_count = 0;
|
||||
memset(&context->perf_params, 0, sizeof(context->perf_params));
|
||||
memset(&context->scratch, 0, sizeof(context->scratch));
|
||||
}
|
||||
|
||||
void dc_resource_state_copy_construct(
|
||||
const struct dc_state *src_ctx,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
int i, j;
|
||||
struct kref refcount = dst_ctx->refcount;
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
struct dml2_context *dml2 = NULL;
|
||||
|
||||
// Need to preserve allocated dml2 context
|
||||
if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
|
||||
dml2 = dst_ctx->bw_ctx.dml2;
|
||||
#endif
|
||||
|
||||
*dst_ctx = *src_ctx;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
// Preserve allocated dml2 context
|
||||
if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
|
||||
dst_ctx->bw_ctx.dml2 = dml2;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
}
|
||||
|
||||
for (i = 0; i < dst_ctx->stream_count; i++) {
|
||||
dc_stream_retain(dst_ctx->streams[i]);
|
||||
for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
dst_ctx->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
/* context refcount should not be overridden */
|
||||
dst_ctx->refcount = refcount;
|
||||
|
||||
}
|
||||
|
||||
struct clock_source *dc_resource_find_first_free_pll(
|
||||
struct resource_context *res_ctx,
|
||||
const struct resource_pool *pool)
|
||||
|
@ -5311,6 +4986,20 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
|
|||
return DC_OK;
|
||||
}
|
||||
|
||||
bool resource_subvp_in_use(struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_NONE)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream)
|
||||
{
|
||||
if (!dc->debug.disable_subvp_high_refresh && is_subvp_high_refresh_candidate(stream))
|
||||
|
|
865
drivers/gpu/drm/amd/display/dc/core/dc_state.c
Normal file
865
drivers/gpu/drm/amd/display/dc/core/dc_state.c
Normal file
|
@ -0,0 +1,865 @@
|
|||
/*
|
||||
* Copyright 2023 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 "core_types.h"
|
||||
#include "core_status.h"
|
||||
#include "dc_state.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "dc_stream_priv.h"
|
||||
#include "dc_plane_priv.h"
|
||||
|
||||
#include "dm_services.h"
|
||||
#include "resource.h"
|
||||
#include "link_enc_cfg.h"
|
||||
|
||||
#include "dml2/dml2_wrapper.h"
|
||||
#include "dml2/dml2_internal_types.h"
|
||||
|
||||
#define DC_LOGGER \
|
||||
dc->ctx->logger
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
/* Private dc_state helper functions */
|
||||
static bool dc_state_track_phantom_stream(struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
if (state->phantom_stream_count >= MAX_PHANTOM_PIPES)
|
||||
return false;
|
||||
|
||||
state->phantom_streams[state->phantom_stream_count++] = phantom_stream;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dc_state_untrack_phantom_stream(struct dc_state *state, struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
bool res = false;
|
||||
int i;
|
||||
|
||||
/* first find phantom stream in the dc_state */
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
if (state->phantom_streams[i] == phantom_stream) {
|
||||
state->phantom_streams[i] = NULL;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* failed to find stream in state */
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
/* trim back phantom streams */
|
||||
state->phantom_stream_count--;
|
||||
for (; i < state->phantom_stream_count; i++)
|
||||
state->phantom_streams[i] = state->phantom_streams[i + 1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool dc_state_is_phantom_stream_tracked(struct dc_state *state, struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
if (state->phantom_streams[i] == phantom_stream)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dc_state_track_phantom_plane(struct dc_state *state,
|
||||
struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
if (state->phantom_plane_count >= MAX_PHANTOM_PIPES)
|
||||
return false;
|
||||
|
||||
state->phantom_planes[state->phantom_plane_count++] = phantom_plane;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dc_state_untrack_phantom_plane(struct dc_state *state, struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
bool res = false;
|
||||
int i;
|
||||
|
||||
/* first find phantom plane in the dc_state */
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
if (state->phantom_planes[i] == phantom_plane) {
|
||||
state->phantom_planes[i] = NULL;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* failed to find plane in state */
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
/* trim back phantom planes */
|
||||
state->phantom_plane_count--;
|
||||
for (; i < state->phantom_plane_count; i++)
|
||||
state->phantom_planes[i] = state->phantom_planes[i + 1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool dc_state_is_phantom_plane_tracked(struct dc_state *state, struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
if (state->phantom_planes[i] == phantom_plane)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void dc_state_copy_internal(struct dc_state *dst_state, struct dc_state *src_state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
memcpy(dst_state, src_state, sizeof(struct dc_state));
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &dst_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
}
|
||||
|
||||
/* retain phantoms */
|
||||
for (i = 0; i < dst_state->phantom_stream_count; i++)
|
||||
dc_stream_retain(dst_state->phantom_streams[i]);
|
||||
|
||||
for (i = 0; i < dst_state->phantom_plane_count; i++)
|
||||
dc_plane_state_retain(dst_state->phantom_planes[i]);
|
||||
|
||||
/* retain streams and planes */
|
||||
for (i = 0; i < dst_state->stream_count; i++) {
|
||||
dc_stream_retain(dst_state->streams[i]);
|
||||
for (j = 0; j < dst_state->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
dst_state->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void init_state(struct dc *dc, struct dc_state *state)
|
||||
{
|
||||
/* Each context must have their own instance of VBA and in order to
|
||||
* initialize and obtain IP and SOC the base DML instance from DC is
|
||||
* initially copied into every context
|
||||
*/
|
||||
memcpy(&state->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
|
||||
}
|
||||
|
||||
/* Public dc_state functions */
|
||||
struct dc_state *dc_state_create(struct dc *dc)
|
||||
{
|
||||
struct dc_state *state = kvzalloc(sizeof(struct dc_state),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
init_state(dc, state);
|
||||
dc_state_construct(dc, state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (dc->debug.using_dml2)
|
||||
dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2);
|
||||
#endif
|
||||
|
||||
kref_init(&state->refcount);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state)
|
||||
{
|
||||
struct kref refcount = dst_state->refcount;
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
struct dml2_context *dst_dml2 = dst_state->bw_ctx.dml2;
|
||||
#endif
|
||||
|
||||
dc_state_copy_internal(dst_state, src_state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
dst_state->bw_ctx.dml2 = dst_dml2;
|
||||
if (src_state->bw_ctx.dml2)
|
||||
dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
|
||||
#endif
|
||||
|
||||
/* context refcount should not be overridden */
|
||||
dst_state->refcount = refcount;
|
||||
}
|
||||
|
||||
struct dc_state *dc_state_create_copy(struct dc_state *src_state)
|
||||
{
|
||||
struct dc_state *new_state;
|
||||
|
||||
new_state = kvmalloc(sizeof(struct dc_state),
|
||||
GFP_KERNEL);
|
||||
if (!new_state)
|
||||
return NULL;
|
||||
|
||||
dc_state_copy_internal(new_state, src_state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (src_state->bw_ctx.dml2 &&
|
||||
!dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
kref_init(&new_state->refcount);
|
||||
|
||||
return new_state;
|
||||
}
|
||||
|
||||
void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state)
|
||||
{
|
||||
dc_state_copy(dst_state, dc->current_state);
|
||||
}
|
||||
|
||||
struct dc_state *dc_state_create_current_copy(struct dc *dc)
|
||||
{
|
||||
return dc_state_create_copy(dc->current_state);
|
||||
}
|
||||
|
||||
void dc_state_construct(struct dc *dc, struct dc_state *state)
|
||||
{
|
||||
state->clk_mgr = dc->clk_mgr;
|
||||
|
||||
/* Initialise DIG link encoder resource tracking variables. */
|
||||
link_enc_cfg_init(dc, state);
|
||||
}
|
||||
|
||||
void dc_state_destruct(struct dc_state *state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
for (j = 0; j < state->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_release(
|
||||
state->stream_status[i].plane_states[j]);
|
||||
|
||||
state->stream_status[i].plane_count = 0;
|
||||
dc_stream_release(state->streams[i]);
|
||||
state->streams[i] = NULL;
|
||||
}
|
||||
state->stream_count = 0;
|
||||
|
||||
/* release tracked phantoms */
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
dc_stream_release(state->phantom_streams[i]);
|
||||
state->phantom_streams[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
dc_plane_state_release(state->phantom_planes[i]);
|
||||
state->phantom_planes[i] = NULL;
|
||||
}
|
||||
state->stream_mask = 0;
|
||||
memset(&state->res_ctx, 0, sizeof(state->res_ctx));
|
||||
memset(&state->pp_display_cfg, 0, sizeof(state->pp_display_cfg));
|
||||
memset(&state->dcn_bw_vars, 0, sizeof(state->dcn_bw_vars));
|
||||
state->clk_mgr = NULL;
|
||||
memset(&state->bw_ctx.bw, 0, sizeof(state->bw_ctx.bw));
|
||||
memset(state->block_sequence, 0, sizeof(state->block_sequence));
|
||||
state->block_sequence_steps = 0;
|
||||
memset(state->dc_dmub_cmd, 0, sizeof(state->dc_dmub_cmd));
|
||||
state->dmub_cmd_count = 0;
|
||||
memset(&state->perf_params, 0, sizeof(state->perf_params));
|
||||
memset(&state->scratch, 0, sizeof(state->scratch));
|
||||
}
|
||||
|
||||
void dc_state_retain(struct dc_state *state)
|
||||
{
|
||||
kref_get(&state->refcount);
|
||||
}
|
||||
|
||||
static void dc_state_free(struct kref *kref)
|
||||
{
|
||||
struct dc_state *state = container_of(kref, struct dc_state, refcount);
|
||||
|
||||
dc_state_destruct(state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
dml2_destroy(state->bw_ctx.dml2);
|
||||
state->bw_ctx.dml2 = 0;
|
||||
#endif
|
||||
|
||||
kvfree(state);
|
||||
}
|
||||
|
||||
void dc_state_release(struct dc_state *state)
|
||||
{
|
||||
kref_put(&state->refcount, dc_state_free);
|
||||
}
|
||||
/*
|
||||
* dc_state_add_stream() - Add a new dc_stream_state to a dc_state.
|
||||
*/
|
||||
enum dc_status dc_state_add_stream(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
enum dc_status res;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (state->stream_count >= dc->res_pool->timing_generator_count) {
|
||||
DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
state->streams[state->stream_count] = stream;
|
||||
dc_stream_retain(stream);
|
||||
state->stream_count++;
|
||||
|
||||
res = resource_add_otg_master_for_stream_output(
|
||||
state, dc->res_pool, stream);
|
||||
if (res != DC_OK)
|
||||
DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* dc_state_remove_stream() - Remove a stream from a dc_state.
|
||||
*/
|
||||
enum dc_status dc_state_remove_stream(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
int i;
|
||||
struct pipe_ctx *del_pipe = resource_get_otg_master_for_stream(
|
||||
&state->res_ctx, stream);
|
||||
|
||||
if (!del_pipe) {
|
||||
dm_error("Pipe not found for stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
resource_update_pipes_for_stream_with_slice_count(state,
|
||||
dc->current_state, dc->res_pool, stream, 1);
|
||||
resource_remove_otg_master_for_stream_output(
|
||||
state, dc->res_pool, stream);
|
||||
|
||||
for (i = 0; i < state->stream_count; i++)
|
||||
if (state->streams[i] == stream)
|
||||
break;
|
||||
|
||||
if (state->streams[i] != stream) {
|
||||
dm_error("Context doesn't have stream %p !\n", stream);
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
dc_stream_release(state->streams[i]);
|
||||
state->stream_count--;
|
||||
|
||||
/* Trim back arrays */
|
||||
for (; i < state->stream_count; i++) {
|
||||
state->streams[i] = state->streams[i + 1];
|
||||
state->stream_status[i] = state->stream_status[i + 1];
|
||||
}
|
||||
|
||||
state->streams[state->stream_count] = NULL;
|
||||
memset(
|
||||
&state->stream_status[state->stream_count],
|
||||
0,
|
||||
sizeof(state->stream_status[0]));
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
bool dc_state_add_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *state)
|
||||
{
|
||||
struct resource_pool *pool = dc->res_pool;
|
||||
struct pipe_ctx *otg_master_pipe;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
bool added = false;
|
||||
|
||||
stream_status = dc_state_get_stream_status(state, stream);
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream not found; failed to attach surface!\n");
|
||||
goto out;
|
||||
} else if (stream_status->plane_count == MAX_SURFACE_NUM) {
|
||||
dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n",
|
||||
plane_state, MAX_SURFACE_NUM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
otg_master_pipe = resource_get_otg_master_for_stream(
|
||||
&state->res_ctx, stream);
|
||||
added = resource_append_dpp_pipes_for_plane_composition(state,
|
||||
dc->current_state, pool, otg_master_pipe, plane_state);
|
||||
|
||||
if (added) {
|
||||
stream_status->plane_states[stream_status->plane_count] =
|
||||
plane_state;
|
||||
stream_status->plane_count++;
|
||||
dc_plane_state_retain(plane_state);
|
||||
}
|
||||
|
||||
out:
|
||||
return added;
|
||||
}
|
||||
|
||||
bool dc_state_remove_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct resource_pool *pool = dc->res_pool;
|
||||
|
||||
if (!plane_state)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++)
|
||||
if (state->streams[i] == stream) {
|
||||
stream_status = &state->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream not found; failed to remove plane.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
resource_remove_dpp_pipes_for_plane_composition(
|
||||
state, pool, plane_state);
|
||||
|
||||
for (i = 0; i < stream_status->plane_count; i++) {
|
||||
if (stream_status->plane_states[i] == plane_state) {
|
||||
dc_plane_state_release(stream_status->plane_states[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == stream_status->plane_count) {
|
||||
dm_error("Existing plane_state not found; failed to detach it!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
stream_status->plane_count--;
|
||||
|
||||
/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
|
||||
for (; i < stream_status->plane_count; i++)
|
||||
stream_status->plane_states[i] = stream_status->plane_states[i + 1];
|
||||
|
||||
stream_status->plane_states[stream_status->plane_count] = NULL;
|
||||
|
||||
if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
|
||||
/* ODM combine could prevent us from supporting more planes
|
||||
* we will reset ODM slice count back to 1 when all planes have
|
||||
* been removed to maximize the amount of planes supported when
|
||||
* new planes are added.
|
||||
*/
|
||||
resource_update_pipes_for_stream_with_slice_count(
|
||||
state, dc->current_state, dc->res_pool, stream, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_state_rem_all_planes_for_stream - Remove planes attached to the target stream.
|
||||
*
|
||||
* @dc: Current dc state.
|
||||
* @stream: Target stream, which we want to remove the attached plans.
|
||||
* @state: context from which the planes are to be removed.
|
||||
*
|
||||
* Return:
|
||||
* Return true if DC was able to remove all planes from the target
|
||||
* stream, otherwise, return false.
|
||||
*/
|
||||
bool dc_state_rem_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i, old_plane_count;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
|
||||
|
||||
for (i = 0; i < state->stream_count; i++)
|
||||
if (state->streams[i] == stream) {
|
||||
stream_status = &state->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream %p not found!\n", stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
old_plane_count = stream_status->plane_count;
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
del_planes[i] = stream_status->plane_states[i];
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
if (!dc_state_remove_plane(dc, stream, del_planes[i], state))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_state_add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state * const *plane_states,
|
||||
int plane_count,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
bool result = true;
|
||||
|
||||
for (i = 0; i < plane_count; i++)
|
||||
if (!dc_state_add_plane(dc, stream, plane_states[i], state)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Private dc_state functions */
|
||||
|
||||
/**
|
||||
* dc_state_get_stream_status - Get stream status from given dc state
|
||||
* @state: DC state to find the stream status in
|
||||
* @stream: The stream to get the stream status for
|
||||
*
|
||||
* The given stream is expected to exist in the given dc state. Otherwise, NULL
|
||||
* will be returned.
|
||||
*/
|
||||
struct dc_stream_status *dc_state_get_stream_status(
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (stream == state->streams[i])
|
||||
return &state->stream_status[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum mall_stream_type dc_state_get_pipe_subvp_type(const struct dc_state *state,
|
||||
const struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
return dc_state_get_stream_subvp_type(state, pipe_ctx->stream);
|
||||
}
|
||||
|
||||
enum mall_stream_type dc_state_get_stream_subvp_type(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
enum mall_stream_type type = SUBVP_NONE;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i] == stream) {
|
||||
type = state->stream_status[i].mall_stream_config.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct dc_stream_state *paired_stream = NULL;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i] == stream) {
|
||||
paired_stream = state->stream_status[i].mall_stream_config.paired_stream;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return paired_stream;
|
||||
}
|
||||
|
||||
struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *main_stream)
|
||||
{
|
||||
struct dc_stream_state *phantom_stream;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
phantom_stream = dc_create_stream_for_sink(main_stream->sink);
|
||||
|
||||
if (!phantom_stream) {
|
||||
DC_LOG_ERROR("Failed to allocate phantom stream.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* track phantom stream in dc_state */
|
||||
dc_state_track_phantom_stream(state, phantom_stream);
|
||||
|
||||
phantom_stream->is_phantom = true;
|
||||
phantom_stream->signal = SIGNAL_TYPE_VIRTUAL;
|
||||
phantom_stream->dpms_off = true;
|
||||
|
||||
return phantom_stream;
|
||||
}
|
||||
|
||||
void dc_state_release_phantom_stream(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!dc_state_untrack_phantom_stream(state, phantom_stream)) {
|
||||
DC_LOG_ERROR("Failed to free phantom stream %p in dc state %p.\n", phantom_stream, state);
|
||||
return;
|
||||
}
|
||||
|
||||
dc_stream_release(phantom_stream);
|
||||
}
|
||||
|
||||
struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_plane_state *main_plane)
|
||||
{
|
||||
struct dc_plane_state *phantom_plane = dc_create_plane_state(dc);
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!phantom_plane) {
|
||||
DC_LOG_ERROR("Failed to allocate phantom plane.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* track phantom inside dc_state */
|
||||
dc_state_track_phantom_plane(state, phantom_plane);
|
||||
|
||||
phantom_plane->is_phantom = true;
|
||||
|
||||
return phantom_plane;
|
||||
}
|
||||
|
||||
void dc_state_release_phantom_plane(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!dc_state_untrack_phantom_plane(state, phantom_plane)) {
|
||||
DC_LOG_ERROR("Failed to free phantom plane %p in dc state %p.\n", phantom_plane, state);
|
||||
return;
|
||||
}
|
||||
|
||||
dc_plane_state_release(phantom_plane);
|
||||
}
|
||||
|
||||
/* add phantom streams to context and generate correct meta inside dc_state */
|
||||
enum dc_status dc_state_add_phantom_stream(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_stream_state *main_stream)
|
||||
{
|
||||
struct dc_stream_status *main_stream_status;
|
||||
struct dc_stream_status *phantom_stream_status;
|
||||
enum dc_status res = dc_state_add_stream(dc, state, phantom_stream);
|
||||
|
||||
/* check if stream is tracked */
|
||||
if (res == DC_OK && !dc_state_is_phantom_stream_tracked(state, phantom_stream)) {
|
||||
/* stream must be tracked if added to state */
|
||||
dc_state_track_phantom_stream(state, phantom_stream);
|
||||
}
|
||||
|
||||
/* setup subvp meta */
|
||||
main_stream_status = dc_state_get_stream_status(state, main_stream);
|
||||
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
|
||||
phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
|
||||
phantom_stream_status->mall_stream_config.paired_stream = main_stream;
|
||||
main_stream_status->mall_stream_config.type = SUBVP_MAIN;
|
||||
main_stream_status->mall_stream_config.paired_stream = phantom_stream;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
enum dc_status dc_state_remove_phantom_stream(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
struct dc_stream_status *main_stream_status;
|
||||
struct dc_stream_status *phantom_stream_status;
|
||||
|
||||
/* reset subvp meta */
|
||||
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
|
||||
main_stream_status = dc_state_get_stream_status(state, phantom_stream_status->mall_stream_config.paired_stream);
|
||||
phantom_stream_status->mall_stream_config.type = SUBVP_NONE;
|
||||
phantom_stream_status->mall_stream_config.paired_stream = NULL;
|
||||
if (main_stream_status) {
|
||||
main_stream_status->mall_stream_config.type = SUBVP_NONE;
|
||||
main_stream_status->mall_stream_config.paired_stream = NULL;
|
||||
}
|
||||
|
||||
/* remove stream from state */
|
||||
return dc_state_remove_stream(dc, state, phantom_stream);
|
||||
}
|
||||
|
||||
bool dc_state_add_phantom_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state *phantom_plane,
|
||||
struct dc_state *state)
|
||||
{
|
||||
bool res = dc_state_add_plane(dc, phantom_stream, phantom_plane, state);
|
||||
|
||||
/* check if stream is tracked */
|
||||
if (res && !dc_state_is_phantom_plane_tracked(state, phantom_plane)) {
|
||||
/* stream must be tracked if added to state */
|
||||
dc_state_track_phantom_plane(state, phantom_plane);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool dc_state_remove_phantom_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state *phantom_plane,
|
||||
struct dc_state *state)
|
||||
{
|
||||
return dc_state_remove_plane(dc, phantom_stream, phantom_plane, state);
|
||||
}
|
||||
|
||||
bool dc_state_rem_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_state *state,
|
||||
bool should_release_planes)
|
||||
{
|
||||
int i, old_plane_count;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
|
||||
|
||||
for (i = 0; i < state->stream_count; i++)
|
||||
if (state->streams[i] == phantom_stream) {
|
||||
stream_status = &state->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream %p not found!\n", phantom_stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
old_plane_count = stream_status->plane_count;
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
del_planes[i] = stream_status->plane_states[i];
|
||||
|
||||
for (i = 0; i < old_plane_count; i++) {
|
||||
if (!dc_state_remove_plane(dc, phantom_stream, del_planes[i], state))
|
||||
return false;
|
||||
if (should_release_planes)
|
||||
dc_state_release_phantom_plane(dc, state, del_planes[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_state_add_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state * const *phantom_planes,
|
||||
int plane_count,
|
||||
struct dc_state *state)
|
||||
{
|
||||
return dc_state_add_all_planes_for_stream(dc, phantom_stream, phantom_planes, plane_count, state);
|
||||
}
|
||||
|
||||
bool dc_state_remove_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
bool removed_phantom = false;
|
||||
struct dc_stream_state *phantom_stream = NULL;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->plane_state && pipe->stream && dc_state_get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) {
|
||||
phantom_stream = pipe->stream;
|
||||
|
||||
dc_state_rem_all_phantom_planes_for_stream(dc, phantom_stream, state, false);
|
||||
dc_state_remove_phantom_stream(dc, state, phantom_stream);
|
||||
removed_phantom = true;
|
||||
}
|
||||
}
|
||||
return removed_phantom;
|
||||
}
|
||||
|
||||
void dc_state_release_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_stream_count; i++)
|
||||
dc_state_release_phantom_stream(dc, state, state->phantom_streams[i]);
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++)
|
||||
dc_state_release_phantom_plane(dc, state, state->phantom_planes[i]);
|
||||
}
|
|
@ -31,6 +31,8 @@
|
|||
#include "ipp.h"
|
||||
#include "timing_generator.h"
|
||||
#include "dc_dmub_srv.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "dc_stream_priv.h"
|
||||
|
||||
#define DC_LOGGER dc->ctx->logger
|
||||
|
||||
|
@ -54,7 +56,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
|
|||
}
|
||||
}
|
||||
|
||||
static bool dc_stream_construct(struct dc_stream_state *stream,
|
||||
bool dc_stream_construct(struct dc_stream_state *stream,
|
||||
struct dc_sink *dc_sink_data)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
@ -121,13 +123,12 @@ static bool dc_stream_construct(struct dc_stream_state *stream,
|
|||
}
|
||||
stream->out_transfer_func->type = TF_TYPE_BYPASS;
|
||||
|
||||
stream->stream_id = stream->ctx->dc_stream_id_count;
|
||||
stream->ctx->dc_stream_id_count++;
|
||||
dc_stream_assign_stream_id(stream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dc_stream_destruct(struct dc_stream_state *stream)
|
||||
void dc_stream_destruct(struct dc_stream_state *stream)
|
||||
{
|
||||
dc_sink_release(stream->sink);
|
||||
if (stream->out_transfer_func != NULL) {
|
||||
|
@ -136,6 +137,13 @@ static void dc_stream_destruct(struct dc_stream_state *stream)
|
|||
}
|
||||
}
|
||||
|
||||
void dc_stream_assign_stream_id(struct dc_stream_state *stream)
|
||||
{
|
||||
/* MSB is reserved to indicate phantoms */
|
||||
stream->stream_id = stream->ctx->dc_stream_id_count;
|
||||
stream->ctx->dc_stream_id_count++;
|
||||
}
|
||||
|
||||
void dc_stream_retain(struct dc_stream_state *stream)
|
||||
{
|
||||
kref_get(&stream->refcount);
|
||||
|
@ -196,8 +204,7 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
|
|||
if (new_stream->out_transfer_func)
|
||||
dc_transfer_func_retain(new_stream->out_transfer_func);
|
||||
|
||||
new_stream->stream_id = new_stream->ctx->dc_stream_id_count;
|
||||
new_stream->ctx->dc_stream_id_count++;
|
||||
dc_stream_assign_stream_id(new_stream);
|
||||
|
||||
/* If using dynamic encoder assignment, wait till stream committed to assign encoder. */
|
||||
if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign)
|
||||
|
@ -208,31 +215,6 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
|
|||
return new_stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_stream_get_status_from_state - Get stream status from given dc state
|
||||
* @state: DC state to find the stream status in
|
||||
* @stream: The stream to get the stream status for
|
||||
*
|
||||
* The given stream is expected to exist in the given dc state. Otherwise, NULL
|
||||
* will be returned.
|
||||
*/
|
||||
struct dc_stream_status *dc_stream_get_status_from_state(
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (stream == state->streams[i])
|
||||
return &state->stream_status[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_stream_get_status() - Get current stream status of the given stream state
|
||||
* @stream: The stream to get the stream status for.
|
||||
|
@ -244,7 +226,7 @@ struct dc_stream_status *dc_stream_get_status(
|
|||
struct dc_stream_state *stream)
|
||||
{
|
||||
struct dc *dc = stream->ctx->dc;
|
||||
return dc_stream_get_status_from_state(dc->current_state, stream);
|
||||
return dc_state_get_stream_status(dc->current_state, stream);
|
||||
}
|
||||
|
||||
static void program_cursor_attributes(
|
||||
|
@ -465,7 +447,8 @@ bool dc_stream_add_writeback(struct dc *dc,
|
|||
if (dc->hwss.enable_writeback) {
|
||||
struct dc_stream_status *stream_status = dc_stream_get_status(stream);
|
||||
struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
|
||||
dwb->otg_inst = stream_status->primary_otg_inst;
|
||||
if (stream_status)
|
||||
dwb->otg_inst = stream_status->primary_otg_inst;
|
||||
}
|
||||
|
||||
if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
|
||||
|
|
|
@ -32,10 +32,12 @@
|
|||
#include "transform.h"
|
||||
#include "dpp.h"
|
||||
|
||||
#include "dc_plane_priv.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Private functions
|
||||
******************************************************************************/
|
||||
static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state)
|
||||
void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state)
|
||||
{
|
||||
plane_state->ctx = ctx;
|
||||
|
||||
|
@ -63,7 +65,7 @@ static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *pl
|
|||
|
||||
}
|
||||
|
||||
static void dc_plane_destruct(struct dc_plane_state *plane_state)
|
||||
void dc_plane_destruct(struct dc_plane_state *plane_state)
|
||||
{
|
||||
if (plane_state->gamma_correction != NULL) {
|
||||
dc_gamma_release(&plane_state->gamma_correction);
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define DC_INTERFACE_H_
|
||||
|
||||
#include "dc_types.h"
|
||||
#include "dc_state.h"
|
||||
#include "dc_plane.h"
|
||||
#include "grph_object_defs.h"
|
||||
#include "logger_types.h"
|
||||
#include "hdcp_msg_types.h"
|
||||
|
@ -49,7 +51,7 @@ struct aux_payload;
|
|||
struct set_config_cmd_payload;
|
||||
struct dmub_notification;
|
||||
|
||||
#define DC_VER "3.2.264"
|
||||
#define DC_VER "3.2.265"
|
||||
|
||||
#define MAX_SURFACES 3
|
||||
#define MAX_PLANES 6
|
||||
|
@ -461,6 +463,12 @@ enum dml_hostvm_override_opts {
|
|||
DML_HOSTVM_OVERRIDE_TRUE = 0x2,
|
||||
};
|
||||
|
||||
enum dc_replay_power_opts {
|
||||
replay_power_opt_invalid = 0x0,
|
||||
replay_power_opt_smu_opt_static_screen = 0x1,
|
||||
replay_power_opt_z10_static_screen = 0x10,
|
||||
};
|
||||
|
||||
enum dcc_option {
|
||||
DCC_ENABLE = 0,
|
||||
DCC_DISABLE = 1,
|
||||
|
@ -979,6 +987,8 @@ struct dc_debug_options {
|
|||
unsigned int ips2_eval_delay_us;
|
||||
unsigned int ips2_entry_delay_us;
|
||||
bool disable_timeout;
|
||||
bool disable_extblankadj;
|
||||
unsigned int static_screen_wait_frames;
|
||||
};
|
||||
|
||||
struct gpu_info_soc_bounding_box_v1_0;
|
||||
|
@ -1026,7 +1036,6 @@ struct dc {
|
|||
|
||||
/* Require to optimize clocks and bandwidth for added/removed planes */
|
||||
bool optimized_required;
|
||||
bool wm_optimized_required;
|
||||
bool idle_optimizations_allowed;
|
||||
bool enable_c20_dtm_b0;
|
||||
|
||||
|
@ -1389,13 +1398,6 @@ struct dc_surface_update {
|
|||
/*
|
||||
* Create a new surface with default parameters;
|
||||
*/
|
||||
struct dc_plane_state *dc_create_plane_state(struct dc *dc);
|
||||
const struct dc_plane_status *dc_plane_get_status(
|
||||
const struct dc_plane_state *plane_state);
|
||||
|
||||
void dc_plane_state_retain(struct dc_plane_state *plane_state);
|
||||
void dc_plane_state_release(struct dc_plane_state *plane_state);
|
||||
|
||||
void dc_gamma_retain(struct dc_gamma *dc_gamma);
|
||||
void dc_gamma_release(struct dc_gamma **dc_gamma);
|
||||
struct dc_gamma *dc_create_gamma(void);
|
||||
|
@ -1459,37 +1461,20 @@ enum dc_status dc_validate_global_state(
|
|||
struct dc_state *new_ctx,
|
||||
bool fast_validate);
|
||||
|
||||
|
||||
void dc_resource_state_construct(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
bool dc_acquire_release_mpc_3dlut(
|
||||
struct dc *dc, bool acquire,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_3dlut **lut,
|
||||
struct dc_transfer_func **shaper);
|
||||
|
||||
void dc_resource_state_copy_construct(
|
||||
const struct dc_state *src_ctx,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
void dc_resource_state_copy_construct_current(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
void dc_resource_state_destruct(struct dc_state *context);
|
||||
|
||||
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
|
||||
void get_audio_check(struct audio_info *aud_modes,
|
||||
struct audio_check *aud_chk);
|
||||
|
||||
enum dc_status dc_commit_streams(struct dc *dc,
|
||||
struct dc_stream_state *streams[],
|
||||
uint8_t stream_count);
|
||||
|
||||
struct dc_state *dc_create_state(struct dc *dc);
|
||||
struct dc_state *dc_copy_state(struct dc_state *src_ctx);
|
||||
void dc_retain_state(struct dc_state *context);
|
||||
void dc_release_state(struct dc_state *context);
|
||||
|
||||
struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
|
@ -2098,6 +2083,20 @@ bool dc_link_setup_psr(struct dc_link *dc_link,
|
|||
const struct dc_stream_state *stream, struct psr_config *psr_config,
|
||||
struct psr_context *psr_context);
|
||||
|
||||
/*
|
||||
* Communicate with DMUB to allow or disallow Panel Replay on the specified link:
|
||||
*
|
||||
* @link: pointer to the dc_link struct instance
|
||||
* @enable: enable(active) or disable(inactive) replay
|
||||
* @wait: state transition need to wait the active set completed.
|
||||
* @force_static: force disable(inactive) the replay
|
||||
* @power_opts: set power optimazation parameters to DMUB.
|
||||
*
|
||||
* return: allow Replay active will return true, else will return false.
|
||||
*/
|
||||
bool dc_link_set_replay_allow_active(struct dc_link *dc_link, const bool *enable,
|
||||
bool wait, bool force_static, const unsigned int *power_opts);
|
||||
|
||||
bool dc_link_get_replay_state(const struct dc_link *dc_link, uint64_t *state);
|
||||
|
||||
/* On eDP links this function call will stall until T12 has elapsed.
|
||||
|
@ -2193,11 +2192,11 @@ int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link(
|
|||
*
|
||||
* @dc: pointer to dc struct
|
||||
* @stream: pointer to all possible streams
|
||||
* @num_streams: number of valid DPIA streams
|
||||
* @count: number of valid DPIA streams
|
||||
*
|
||||
* return: TRUE if bw used by DPIAs doesn't exceed available BW else return FALSE
|
||||
*/
|
||||
bool dc_link_validate(struct dc *dc, const struct dc_stream_state *streams,
|
||||
bool dc_link_dp_dpia_validate(struct dc *dc, const struct dc_stream_state *streams,
|
||||
const unsigned int count);
|
||||
|
||||
/* Sink Interfaces - A sink corresponds to a display output device */
|
||||
|
@ -2342,6 +2341,9 @@ void dc_hardware_release(struct dc *dc);
|
|||
void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc);
|
||||
|
||||
bool dc_set_psr_allow_active(struct dc *dc, bool enable);
|
||||
|
||||
bool dc_set_replay_allow_active(struct dc *dc, bool active);
|
||||
|
||||
void dc_z10_restore(const struct dc *dc);
|
||||
void dc_z10_save_init(struct dc *dc);
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "cursor_reg_cache.h"
|
||||
#include "resource.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dc_state_priv.h"
|
||||
|
||||
#define CTX dc_dmub_srv->ctx
|
||||
#define DC_LOGGER CTX->logger
|
||||
|
@ -140,7 +141,10 @@ bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
|
|||
|
||||
if (status == DMUB_STATUS_QUEUE_FULL) {
|
||||
/* Execute and wait for queue to become empty again. */
|
||||
dmub_srv_cmd_execute(dmub);
|
||||
status = dmub_srv_cmd_execute(dmub);
|
||||
if (status == DMUB_STATUS_POWER_STATE_D3)
|
||||
return false;
|
||||
|
||||
dmub_srv_wait_for_idle(dmub, 100000);
|
||||
|
||||
/* Requeue the command. */
|
||||
|
@ -148,16 +152,20 @@ bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
|
|||
}
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
if (status != DMUB_STATUS_POWER_STATE_D3) {
|
||||
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
status = dmub_srv_cmd_execute(dmub);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
if (status != DMUB_STATUS_POWER_STATE_D3) {
|
||||
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -218,7 +226,10 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun
|
|||
|
||||
if (status == DMUB_STATUS_QUEUE_FULL) {
|
||||
/* Execute and wait for queue to become empty again. */
|
||||
dmub_srv_cmd_execute(dmub);
|
||||
status = dmub_srv_cmd_execute(dmub);
|
||||
if (status == DMUB_STATUS_POWER_STATE_D3)
|
||||
return false;
|
||||
|
||||
dmub_srv_wait_for_idle(dmub, 100000);
|
||||
|
||||
/* Requeue the command. */
|
||||
|
@ -226,16 +237,20 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun
|
|||
}
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
if (status != DMUB_STATUS_POWER_STATE_D3) {
|
||||
DC_ERROR("Error queueing DMUB command: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
status = dmub_srv_cmd_execute(dmub);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
if (status != DMUB_STATUS_POWER_STATE_D3) {
|
||||
DC_ERROR("Error starting DMUB execution: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -287,17 +302,11 @@ bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv)
|
|||
bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
|
||||
unsigned int stream_mask)
|
||||
{
|
||||
struct dmub_srv *dmub;
|
||||
const uint32_t timeout = 30;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
return dmub_srv_send_gpint_command(
|
||||
dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
|
||||
stream_mask, timeout) == DMUB_STATUS_OK;
|
||||
return dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
|
||||
stream_mask, NULL, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv)
|
||||
|
@ -346,7 +355,7 @@ void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal
|
|||
cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
|
||||
|
||||
// Send the command to the DMCUB.
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst)
|
||||
|
@ -360,7 +369,7 @@ void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst)
|
|||
cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header);
|
||||
|
||||
// Send the command to the DMCUB.
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream)
|
||||
|
@ -453,7 +462,7 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru
|
|||
sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header);
|
||||
|
||||
// Send the command to the DMCUB.
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -474,7 +483,7 @@ void dc_dmub_srv_query_caps_cmd(struct dc_dmub_srv *dc_dmub_srv)
|
|||
cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data);
|
||||
|
||||
/* If command was processed, copy feature caps to dmub srv */
|
||||
if (dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
|
||||
if (dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
|
||||
cmd.query_feature_caps.header.ret_status == 0) {
|
||||
memcpy(&dc_dmub_srv->dmub->feature_caps,
|
||||
&cmd.query_feature_caps.query_feature_caps_data,
|
||||
|
@ -499,7 +508,7 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
|
|||
cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst;
|
||||
|
||||
// If command was processed, copy feature caps to dmub srv
|
||||
if (dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
|
||||
if (dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) &&
|
||||
cmd.visual_confirm_color.header.ret_status == 0) {
|
||||
memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color,
|
||||
&cmd.visual_confirm_color.visual_confirm_color_data,
|
||||
|
@ -510,10 +519,11 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
|
|||
/**
|
||||
* populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command
|
||||
*
|
||||
* @dc: [in] current dc state
|
||||
* @dc: [in] pointer to dc object
|
||||
* @subvp_pipe: [in] pipe_ctx for the SubVP pipe
|
||||
* @vblank_pipe: [in] pipe_ctx for the DRR pipe
|
||||
* @pipe_data: [in] Pipe data which stores the VBLANK/DRR info
|
||||
* @context: [in] DC state for access to phantom stream
|
||||
*
|
||||
* Populate the DMCUB SubVP command with DRR pipe info. All the information
|
||||
* required for calculating the SubVP + DRR microschedule is populated here.
|
||||
|
@ -524,12 +534,14 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
|
|||
* 3. Populate the drr_info with the min and max supported vtotal values
|
||||
*/
|
||||
static void populate_subvp_cmd_drr_info(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct pipe_ctx *subvp_pipe,
|
||||
struct pipe_ctx *vblank_pipe,
|
||||
struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data)
|
||||
{
|
||||
struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
|
||||
struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
|
||||
struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
|
||||
struct dc_crtc_timing *phantom_timing = &phantom_stream->timing;
|
||||
struct dc_crtc_timing *drr_timing = &vblank_pipe->stream->timing;
|
||||
uint16_t drr_frame_us = 0;
|
||||
uint16_t min_drr_supported_us = 0;
|
||||
|
@ -617,7 +629,7 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
|
|||
continue;
|
||||
|
||||
// Find the SubVP pipe
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -634,7 +646,7 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
|
|||
|
||||
if (vblank_pipe->stream->ignore_msa_timing_param &&
|
||||
(vblank_pipe->stream->allow_freesync || vblank_pipe->stream->vrr_active_variable || vblank_pipe->stream->vrr_active_fixed))
|
||||
populate_subvp_cmd_drr_info(dc, pipe, vblank_pipe, pipe_data);
|
||||
populate_subvp_cmd_drr_info(dc, context, pipe, vblank_pipe, pipe_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,10 +671,17 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
|
|||
uint32_t subvp0_prefetch_us = 0;
|
||||
uint32_t subvp1_prefetch_us = 0;
|
||||
uint32_t prefetch_delta_us = 0;
|
||||
struct dc_crtc_timing *phantom_timing0 = &subvp_pipes[0]->stream->mall_stream_config.paired_stream->timing;
|
||||
struct dc_crtc_timing *phantom_timing1 = &subvp_pipes[1]->stream->mall_stream_config.paired_stream->timing;
|
||||
struct dc_stream_state *phantom_stream0 = NULL;
|
||||
struct dc_stream_state *phantom_stream1 = NULL;
|
||||
struct dc_crtc_timing *phantom_timing0 = NULL;
|
||||
struct dc_crtc_timing *phantom_timing1 = NULL;
|
||||
struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL;
|
||||
|
||||
phantom_stream0 = dc_state_get_paired_subvp_stream(context, subvp_pipes[0]->stream);
|
||||
phantom_stream1 = dc_state_get_paired_subvp_stream(context, subvp_pipes[1]->stream);
|
||||
phantom_timing0 = &phantom_stream0->timing;
|
||||
phantom_timing1 = &phantom_stream1->timing;
|
||||
|
||||
subvp0_prefetch_us = div64_u64(((uint64_t)(phantom_timing0->v_total - phantom_timing0->v_front_porch) *
|
||||
(uint64_t)phantom_timing0->h_total * 1000000),
|
||||
(((uint64_t)phantom_timing0->pix_clk_100hz * 100) + dc->caps.subvp_prefetch_end_to_mall_start_us));
|
||||
|
@ -712,8 +731,9 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
|
|||
uint32_t j;
|
||||
struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data =
|
||||
&cmd->fw_assisted_mclk_switch_v2.config_data.pipe_data[cmd_pipe_index];
|
||||
struct dc_stream_state *phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
|
||||
struct dc_crtc_timing *main_timing = &subvp_pipe->stream->timing;
|
||||
struct dc_crtc_timing *phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
|
||||
struct dc_crtc_timing *phantom_timing = &phantom_stream->timing;
|
||||
uint32_t out_num_stream, out_den_stream, out_num_plane, out_den_plane, out_num, out_den;
|
||||
|
||||
pipe_data->mode = SUBVP;
|
||||
|
@ -767,7 +787,7 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
|
|||
for (j = 0; j < dc->res_pool->pipe_count; j++) {
|
||||
struct pipe_ctx *phantom_pipe = &context->res_ctx.pipe_ctx[j];
|
||||
|
||||
if (phantom_pipe->stream == subvp_pipe->stream->mall_stream_config.paired_stream) {
|
||||
if (phantom_pipe->stream == dc_state_get_paired_subvp_stream(context, subvp_pipe->stream)) {
|
||||
pipe_data->pipe_config.subvp_data.phantom_pipe_index = phantom_pipe->stream_res.tg->inst;
|
||||
if (phantom_pipe->bottom_pipe) {
|
||||
pipe_data->pipe_config.subvp_data.phantom_split_pipe_index = phantom_pipe->bottom_pipe->plane_res.hubp->inst;
|
||||
|
@ -801,6 +821,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
union dmub_rb_cmd cmd;
|
||||
struct pipe_ctx *subvp_pipes[2];
|
||||
uint32_t wm_val_refclk = 0;
|
||||
enum mall_stream_type pipe_mall_type;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
// FW command for SUBVP
|
||||
|
@ -816,7 +837,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
*/
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN)
|
||||
subvp_pipes[subvp_count++] = pipe;
|
||||
}
|
||||
|
||||
|
@ -824,6 +845,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
// For each pipe that is a "main" SUBVP pipe, fill in pipe data for DMUB SUBVP cmd
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe);
|
||||
|
||||
if (!pipe->stream)
|
||||
continue;
|
||||
|
@ -834,12 +856,11 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
*/
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->stream->mall_stream_config.paired_stream &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
pipe_mall_type == SUBVP_MAIN) {
|
||||
populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
|
||||
} else if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
pipe_mall_type == SUBVP_NONE) {
|
||||
// Don't need to check for ActiveDRAMClockChangeMargin < 0, not valid in cases where
|
||||
// we run through DML without calculating "natural" P-state support
|
||||
populate_subvp_cmd_vblank_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
|
||||
|
@ -861,7 +882,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF;
|
||||
}
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
|
||||
|
@ -1098,7 +1119,7 @@ void dc_send_update_cursor_info_to_dmu(
|
|||
pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp);
|
||||
|
||||
/* Combine 2nd cmds update_curosr_info to DMU */
|
||||
dm_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1112,25 +1133,20 @@ bool dc_dmub_check_min_version(struct dmub_srv *srv)
|
|||
void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
struct dmub_srv *dmub;
|
||||
enum dmub_status status;
|
||||
static const uint32_t timeout_us = 30;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
|
||||
DC_LOG_ERROR("%s: invalid parameters.", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1, 0x0010, timeout_us);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1,
|
||||
0x0010, NULL, DM_DMUB_WAIT_TYPE_WAIT)) {
|
||||
DC_LOG_ERROR("timeout updating trace buffer mask word\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK, 0x0000, timeout_us);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK,
|
||||
0x0000, NULL, DM_DMUB_WAIT_TYPE_WAIT)) {
|
||||
DC_LOG_ERROR("timeout updating trace buffer mask word\n");
|
||||
return;
|
||||
}
|
||||
|
@ -1148,6 +1164,9 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
|
|||
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
|
||||
enum dmub_status status;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return true;
|
||||
|
||||
if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation)
|
||||
return true;
|
||||
|
||||
|
@ -1169,7 +1188,7 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait)
|
|||
return true;
|
||||
}
|
||||
|
||||
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
|
||||
static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
|
||||
{
|
||||
union dmub_rb_cmd cmd = {0};
|
||||
|
||||
|
@ -1190,20 +1209,20 @@ void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
|
|||
dc->hwss.set_idle_state(dc, true);
|
||||
}
|
||||
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
/* NOTE: This does not use the "wake" interface since this is part of the wake path. */
|
||||
/* We also do not perform a wait since DMCUB could enter idle after the notification. */
|
||||
dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
||||
static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
||||
{
|
||||
const uint32_t max_num_polls = 10000;
|
||||
uint32_t allow_state = 0;
|
||||
uint32_t commit_state = 0;
|
||||
int i;
|
||||
|
||||
if (dc->debug.dmcub_emulation)
|
||||
return;
|
||||
|
||||
if (!dc->idle_optimizations_allowed)
|
||||
if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub)
|
||||
return;
|
||||
|
||||
if (dc->hwss.get_idle_state &&
|
||||
|
@ -1215,8 +1234,16 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
|||
|
||||
if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) {
|
||||
// Wait for evaluation time
|
||||
udelay(dc->debug.ips2_eval_delay_us);
|
||||
commit_state = dc->hwss.get_idle_state(dc);
|
||||
for (;;) {
|
||||
udelay(dc->debug.ips2_eval_delay_us);
|
||||
commit_state = dc->hwss.get_idle_state(dc);
|
||||
if (commit_state & DMUB_IPS2_ALLOW_MASK)
|
||||
break;
|
||||
|
||||
/* allow was still set, retry eval delay */
|
||||
dc->hwss.set_idle_state(dc, false);
|
||||
}
|
||||
|
||||
if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) {
|
||||
// Tell PMFW to exit low power state
|
||||
dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
|
||||
|
@ -1225,17 +1252,13 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
|||
udelay(dc->debug.ips2_entry_delay_us);
|
||||
dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
|
||||
|
||||
for (i = 0; i < max_num_polls; ++i) {
|
||||
for (;;) {
|
||||
commit_state = dc->hwss.get_idle_state(dc);
|
||||
if (commit_state & DMUB_IPS2_COMMIT_MASK)
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
|
||||
if (dc->debug.disable_timeout)
|
||||
i--;
|
||||
}
|
||||
ASSERT(i < max_num_polls);
|
||||
|
||||
if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true))
|
||||
ASSERT(0);
|
||||
|
@ -1250,17 +1273,13 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
|
|||
|
||||
dc_dmub_srv_notify_idle(dc, false);
|
||||
if (!(allow_state & DMUB_IPS1_ALLOW_MASK)) {
|
||||
for (i = 0; i < max_num_polls; ++i) {
|
||||
for (;;) {
|
||||
commit_state = dc->hwss.get_idle_state(dc);
|
||||
if (commit_state & DMUB_IPS1_COMMIT_MASK)
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
|
||||
if (dc->debug.disable_timeout)
|
||||
i--;
|
||||
}
|
||||
ASSERT(i < max_num_polls);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1282,3 +1301,117 @@ void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_c
|
|||
else
|
||||
dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3);
|
||||
}
|
||||
|
||||
void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return;
|
||||
|
||||
if (dc_dmub_srv->idle_allowed == allow_idle)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Entering a low power state requires a driver notification.
|
||||
* Powering up the hardware requires notifying PMFW and DMCUB.
|
||||
* Clearing the driver idle allow requires a DMCUB command.
|
||||
* DMCUB commands requires the DMCUB to be powered up and restored.
|
||||
*
|
||||
* Exit out early to prevent an infinite loop of DMCUB commands
|
||||
* triggering exit low power - use software state to track this.
|
||||
*/
|
||||
dc_dmub_srv->idle_allowed = allow_idle;
|
||||
|
||||
if (!allow_idle)
|
||||
dc_dmub_srv_exit_low_power_state(dc);
|
||||
else
|
||||
dc_dmub_srv_notify_idle(dc, allow_idle);
|
||||
}
|
||||
|
||||
bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd,
|
||||
enum dm_dmub_wait_type wait_type)
|
||||
{
|
||||
return dc_wake_and_execute_dmub_cmd_list(ctx, 1, cmd, wait_type);
|
||||
}
|
||||
|
||||
bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count,
|
||||
union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv;
|
||||
bool result = false, reallow_idle = false;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
if (count == 0)
|
||||
return true;
|
||||
|
||||
if (dc_dmub_srv->idle_allowed) {
|
||||
dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false);
|
||||
reallow_idle = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* These may have different implementations in DM, so ensure
|
||||
* that we guide it to the expected helper.
|
||||
*/
|
||||
if (count > 1)
|
||||
result = dm_execute_dmub_cmd_list(ctx, count, cmd, wait_type);
|
||||
else
|
||||
result = dm_execute_dmub_cmd(ctx, cmd, wait_type);
|
||||
|
||||
if (result && reallow_idle)
|
||||
dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool dc_dmub_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code,
|
||||
uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv;
|
||||
const uint32_t wait_us = wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT ? 0 : 30;
|
||||
enum dmub_status status;
|
||||
|
||||
if (response)
|
||||
*response = 0;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
status = dmub_srv_send_gpint_command(dc_dmub_srv->dmub, command_code, param, wait_us);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
if (status == DMUB_STATUS_TIMEOUT && wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response && wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
|
||||
dmub_srv_get_gpint_response(dc_dmub_srv->dmub, response);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code,
|
||||
uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type)
|
||||
{
|
||||
struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv;
|
||||
bool result = false, reallow_idle = false;
|
||||
|
||||
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
|
||||
return false;
|
||||
|
||||
if (dc_dmub_srv->idle_allowed) {
|
||||
dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false);
|
||||
reallow_idle = true;
|
||||
}
|
||||
|
||||
result = dc_dmub_execute_gpint(ctx, command_code, param, response, wait_type);
|
||||
|
||||
if (result && reallow_idle)
|
||||
dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ struct dc_dmub_srv {
|
|||
|
||||
struct dc_context *ctx;
|
||||
void *dm;
|
||||
|
||||
bool idle_allowed;
|
||||
};
|
||||
|
||||
void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
|
||||
|
@ -100,8 +102,59 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc);
|
|||
void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index);
|
||||
|
||||
bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait);
|
||||
void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle);
|
||||
void dc_dmub_srv_exit_low_power_state(const struct dc *dc);
|
||||
|
||||
void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle);
|
||||
|
||||
void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState);
|
||||
|
||||
/**
|
||||
* dc_wake_and_execute_dmub_cmd() - Wrapper for DMUB command execution.
|
||||
*
|
||||
* Refer to dc_wake_and_execute_dmub_cmd_list() for usage and limitations,
|
||||
* This function is a convenience wrapper for a single command execution.
|
||||
*
|
||||
* @ctx: DC context
|
||||
* @cmd: The command to send/receive
|
||||
* @wait_type: The wait behavior for the execution
|
||||
*
|
||||
* Return: true on command submission success, false otherwise
|
||||
*/
|
||||
bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd,
|
||||
enum dm_dmub_wait_type wait_type);
|
||||
|
||||
/**
|
||||
* dc_wake_and_execute_dmub_cmd_list() - Wrapper for DMUB command list execution.
|
||||
*
|
||||
* If the DMCUB hardware was asleep then it wakes the DMUB before
|
||||
* executing the command and attempts to re-enter if the command
|
||||
* submission was successful.
|
||||
*
|
||||
* This should be the preferred command submission interface provided
|
||||
* the DC lock is acquired.
|
||||
*
|
||||
* Entry/exit out of idle power optimizations would need to be
|
||||
* manually performed otherwise through dc_allow_idle_optimizations().
|
||||
*
|
||||
* @ctx: DC context
|
||||
* @count: Number of commands to send/receive
|
||||
* @cmd: Array of commands to send
|
||||
* @wait_type: The wait behavior for the execution
|
||||
*
|
||||
* Return: true on command submission success, false otherwise
|
||||
*/
|
||||
bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count,
|
||||
union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
|
||||
|
||||
/**
|
||||
* dc_wake_and_execute_gpint()
|
||||
*
|
||||
* @ctx: DC context
|
||||
* @command_code: The command ID to send to DMCUB
|
||||
* @param: The parameter to message DMCUB
|
||||
* @response: Optional response out value - may be NULL.
|
||||
* @wait_type: The wait behavior for the execution
|
||||
*/
|
||||
bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code,
|
||||
uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type);
|
||||
|
||||
#endif /* _DMUB_DC_SRV_H_ */
|
||||
|
|
|
@ -1377,6 +1377,12 @@ struct dp_trace {
|
|||
#ifndef DP_TUNNELING_STATUS
|
||||
#define DP_TUNNELING_STATUS 0xE0025 /* 1.4a */
|
||||
#endif
|
||||
#ifndef DP_TUNNELING_MAX_LINK_RATE
|
||||
#define DP_TUNNELING_MAX_LINK_RATE 0xE0028 /* 1.4a */
|
||||
#endif
|
||||
#ifndef DP_TUNNELING_MAX_LANE_COUNT
|
||||
#define DP_TUNNELING_MAX_LANE_COUNT 0xE0029 /* 1.4a */
|
||||
#endif
|
||||
#ifndef DPTX_BW_ALLOCATION_MODE_CONTROL
|
||||
#define DPTX_BW_ALLOCATION_MODE_CONTROL 0xE0030 /* 1.4a */
|
||||
#endif
|
||||
|
|
|
@ -50,7 +50,7 @@ static inline void submit_dmub_read_modify_write(
|
|||
cmd_buf->header.payload_bytes =
|
||||
sizeof(struct dmub_cmd_read_modify_write_sequence) * offload->reg_seq_count;
|
||||
|
||||
dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
|
||||
memset(cmd_buf, 0, sizeof(*cmd_buf));
|
||||
|
||||
|
@ -67,7 +67,7 @@ static inline void submit_dmub_burst_write(
|
|||
cmd_buf->header.payload_bytes =
|
||||
sizeof(uint32_t) * offload->reg_seq_count;
|
||||
|
||||
dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
|
||||
memset(cmd_buf, 0, sizeof(*cmd_buf));
|
||||
|
||||
|
@ -80,7 +80,7 @@ static inline void submit_dmub_reg_wait(
|
|||
{
|
||||
struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait;
|
||||
|
||||
dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT);
|
||||
|
||||
memset(cmd_buf, 0, sizeof(*cmd_buf));
|
||||
offload->reg_seq_count = 0;
|
||||
|
|
|
@ -244,7 +244,7 @@ enum pixel_format {
|
|||
#define DC_MAX_DIRTY_RECTS 3
|
||||
struct dc_flip_addrs {
|
||||
struct dc_plane_address address;
|
||||
unsigned int flip_timestamp_in_us;
|
||||
unsigned long long flip_timestamp_in_us;
|
||||
bool flip_immediate;
|
||||
/* TODO: add flip duration for FreeSync */
|
||||
bool triplebuffer_flips;
|
||||
|
|
38
drivers/gpu/drm/amd/display/dc/dc_plane.h
Normal file
38
drivers/gpu/drm/amd/display/dc/dc_plane.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_PLANE_H_
|
||||
#define _DC_PLANE_H_
|
||||
|
||||
#include "dc.h"
|
||||
#include "dc_hw_types.h"
|
||||
|
||||
struct dc_plane_state *dc_create_plane_state(struct dc *dc);
|
||||
const struct dc_plane_status *dc_plane_get_status(
|
||||
const struct dc_plane_state *plane_state);
|
||||
void dc_plane_state_retain(struct dc_plane_state *plane_state);
|
||||
void dc_plane_state_release(struct dc_plane_state *plane_state);
|
||||
|
||||
#endif /* _DC_PLANE_H_ */
|
34
drivers/gpu/drm/amd/display/dc/dc_plane_priv.h
Normal file
34
drivers/gpu/drm/amd/display/dc/dc_plane_priv.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_PLANE_PRIV_H_
|
||||
#define _DC_PLANE_PRIV_H_
|
||||
|
||||
#include "dc_plane.h"
|
||||
|
||||
void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state);
|
||||
void dc_plane_destruct(struct dc_plane_state *plane_state);
|
||||
|
||||
#endif /* _DC_PLANE_PRIV_H_ */
|
78
drivers/gpu/drm/amd/display/dc/dc_state.h
Normal file
78
drivers/gpu/drm/amd/display/dc/dc_state.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_STATE_H_
|
||||
#define _DC_STATE_H_
|
||||
|
||||
#include "dc.h"
|
||||
#include "inc/core_status.h"
|
||||
|
||||
struct dc_state *dc_state_create(struct dc *dc);
|
||||
void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state);
|
||||
struct dc_state *dc_state_create_copy(struct dc_state *src_state);
|
||||
void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state);
|
||||
struct dc_state *dc_state_create_current_copy(struct dc *dc);
|
||||
void dc_state_construct(struct dc *dc, struct dc_state *state);
|
||||
void dc_state_destruct(struct dc_state *state);
|
||||
void dc_state_retain(struct dc_state *state);
|
||||
void dc_state_release(struct dc_state *state);
|
||||
|
||||
enum dc_status dc_state_add_stream(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
enum dc_status dc_state_remove_stream(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
bool dc_state_add_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_remove_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_rem_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state * const *plane_states,
|
||||
int plane_count,
|
||||
struct dc_state *state);
|
||||
|
||||
struct dc_stream_status *dc_state_get_stream_status(
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
#endif /* _DC_STATE_H_ */
|
102
drivers/gpu/drm/amd/display/dc/dc_state_priv.h
Normal file
102
drivers/gpu/drm/amd/display/dc/dc_state_priv.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_STATE_PRIV_H_
|
||||
#define _DC_STATE_PRIV_H_
|
||||
|
||||
#include "dc_state.h"
|
||||
#include "dc_stream.h"
|
||||
|
||||
/* Get the type of the provided resource (none, phantom, main) based on the provided
|
||||
* context. If the context is unavailable, determine only if phantom or not.
|
||||
*/
|
||||
enum mall_stream_type dc_state_get_pipe_subvp_type(const struct dc_state *state,
|
||||
const struct pipe_ctx *pipe_ctx);
|
||||
enum mall_stream_type dc_state_get_stream_subvp_type(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream);
|
||||
|
||||
/* Gets the phantom stream if main is provided, gets the main if phantom is provided.*/
|
||||
struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream);
|
||||
|
||||
/* allocate's phantom stream or plane and returns pointer to the object */
|
||||
struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *main_stream);
|
||||
struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_plane_state *main_plane);
|
||||
|
||||
/* deallocate's phantom stream or plane */
|
||||
void dc_state_release_phantom_stream(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream);
|
||||
void dc_state_release_phantom_plane(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_plane_state *phantom_plane);
|
||||
|
||||
/* add/remove phantom stream to context and generate subvp meta data */
|
||||
enum dc_status dc_state_add_phantom_stream(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_stream_state *main_stream);
|
||||
enum dc_status dc_state_remove_phantom_stream(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream);
|
||||
|
||||
bool dc_state_add_phantom_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state *phantom_plane,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_remove_phantom_plane(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state *phantom_plane,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_rem_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_state *state,
|
||||
bool should_release_planes);
|
||||
|
||||
bool dc_state_add_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_plane_state * const *phantom_planes,
|
||||
int plane_count,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_remove_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state);
|
||||
|
||||
void dc_state_release_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state);
|
||||
|
||||
#endif /* _DC_STATE_PRIV_H_ */
|
|
@ -38,6 +38,14 @@ struct timing_sync_info {
|
|||
bool master;
|
||||
};
|
||||
|
||||
struct mall_stream_config {
|
||||
/* MALL stream config to indicate if the stream is phantom or not.
|
||||
* We will use a phantom stream to indicate that the pipe is phantom.
|
||||
*/
|
||||
enum mall_stream_type type;
|
||||
struct dc_stream_state *paired_stream; // master / slave stream
|
||||
};
|
||||
|
||||
struct dc_stream_status {
|
||||
int primary_otg_inst;
|
||||
int stream_enc_inst;
|
||||
|
@ -50,6 +58,7 @@ struct dc_stream_status {
|
|||
struct timing_sync_info timing_sync_info;
|
||||
struct dc_plane_state *plane_states[MAX_SURFACE_NUM];
|
||||
bool is_abm_supported;
|
||||
struct mall_stream_config mall_stream_config;
|
||||
};
|
||||
|
||||
enum hubp_dmdata_mode {
|
||||
|
@ -130,7 +139,6 @@ union stream_update_flags {
|
|||
uint32_t wb_update:1;
|
||||
uint32_t dsc_changed : 1;
|
||||
uint32_t mst_bw : 1;
|
||||
uint32_t crtc_timing_adjust : 1;
|
||||
uint32_t fams_changed : 1;
|
||||
} bits;
|
||||
|
||||
|
@ -147,31 +155,6 @@ struct test_pattern {
|
|||
|
||||
#define SUBVP_DRR_MARGIN_US 100 // 100us for DRR margin (SubVP + DRR)
|
||||
|
||||
enum mall_stream_type {
|
||||
SUBVP_NONE, // subvp not in use
|
||||
SUBVP_MAIN, // subvp in use, this stream is main stream
|
||||
SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream
|
||||
};
|
||||
|
||||
struct mall_stream_config {
|
||||
/* MALL stream config to indicate if the stream is phantom or not.
|
||||
* We will use a phantom stream to indicate that the pipe is phantom.
|
||||
*/
|
||||
enum mall_stream_type type;
|
||||
struct dc_stream_state *paired_stream; // master / slave stream
|
||||
};
|
||||
|
||||
/* Temp struct used to save and restore MALL config
|
||||
* during validation.
|
||||
*
|
||||
* TODO: Move MALL config into dc_state instead of stream struct
|
||||
* to avoid needing to save/restore.
|
||||
*/
|
||||
struct mall_temp_config {
|
||||
struct mall_stream_config mall_stream_config[MAX_PIPES];
|
||||
bool is_phantom_plane[MAX_PIPES];
|
||||
};
|
||||
|
||||
struct dc_stream_debug_options {
|
||||
char force_odm_combine_segments;
|
||||
};
|
||||
|
@ -301,7 +284,7 @@ struct dc_stream_state {
|
|||
bool has_non_synchronizable_pclk;
|
||||
bool vblank_synchronized;
|
||||
bool fpo_in_use;
|
||||
struct mall_stream_config mall_stream_config;
|
||||
bool is_phantom;
|
||||
};
|
||||
|
||||
#define ABM_LEVEL_IMMEDIATE_DISABLE 255
|
||||
|
@ -342,7 +325,6 @@ struct dc_stream_update {
|
|||
struct dc_3dlut *lut3d_func;
|
||||
|
||||
struct test_pattern *pending_test_pattern;
|
||||
struct dc_crtc_timing_adjust *crtc_timing_adjust;
|
||||
};
|
||||
|
||||
bool dc_is_stream_unchanged(
|
||||
|
@ -415,41 +397,6 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
|
|||
uint32_t *h_position,
|
||||
uint32_t *v_position);
|
||||
|
||||
enum dc_status dc_add_stream_to_ctx(
|
||||
struct dc *dc,
|
||||
struct dc_state *new_ctx,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
enum dc_status dc_remove_stream_from_ctx(
|
||||
struct dc *dc,
|
||||
struct dc_state *new_ctx,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
|
||||
bool dc_add_plane_to_context(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context);
|
||||
|
||||
bool dc_remove_plane_from_context(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context);
|
||||
|
||||
bool dc_rem_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_state *context);
|
||||
|
||||
bool dc_add_all_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state * const *plane_states,
|
||||
int plane_count,
|
||||
struct dc_state *context);
|
||||
|
||||
bool dc_stream_add_writeback(struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_writeback_info *wb_info);
|
||||
|
@ -518,9 +465,6 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink);
|
|||
void dc_stream_retain(struct dc_stream_state *dc_stream);
|
||||
void dc_stream_release(struct dc_stream_state *dc_stream);
|
||||
|
||||
struct dc_stream_status *dc_stream_get_status_from_state(
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
struct dc_stream_status *dc_stream_get_status(
|
||||
struct dc_stream_state *dc_stream);
|
||||
|
||||
|
|
37
drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
Normal file
37
drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2023 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DC_STREAM_PRIV_H_
|
||||
#define _DC_STREAM_PRIV_H_
|
||||
|
||||
#include "dc_stream.h"
|
||||
|
||||
bool dc_stream_construct(struct dc_stream_state *stream,
|
||||
struct dc_sink *dc_sink_data);
|
||||
void dc_stream_destruct(struct dc_stream_state *stream);
|
||||
|
||||
void dc_stream_assign_stream_id(struct dc_stream_state *stream);
|
||||
|
||||
#endif // _DC_STREAM_PRIV_H_
|
|
@ -1151,6 +1151,8 @@ struct dc_dpia_bw_alloc {
|
|||
int bw_granularity; // BW Granularity
|
||||
bool bw_alloc_enabled; // The BW Alloc Mode Support is turned ON for all 3: DP-Tx & Dpia & CM
|
||||
bool response_ready; // Response ready from the CM side
|
||||
uint8_t nrd_max_lane_count; // Non-reduced max lane count
|
||||
uint8_t nrd_max_link_rate; // Non-reduced max link rate
|
||||
};
|
||||
|
||||
#define MAX_SINKS_PER_LINK 4
|
||||
|
@ -1161,4 +1163,9 @@ enum dc_hpd_enable_select {
|
|||
HPD_EN_FOR_SECONDARY_EDP_ONLY,
|
||||
};
|
||||
|
||||
enum mall_stream_type {
|
||||
SUBVP_NONE, // subvp not in use
|
||||
SUBVP_MAIN, // subvp in use, this stream is main stream
|
||||
SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream
|
||||
};
|
||||
#endif /* DC_TYPES_H_ */
|
||||
|
|
|
@ -135,7 +135,7 @@ static void dmcu_set_backlight_level(
|
|||
0, 1, 80000);
|
||||
}
|
||||
|
||||
static void dce_abm_init(struct abm *abm, uint32_t backlight)
|
||||
static void dce_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
|
||||
{
|
||||
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
|
||||
|
||||
|
@ -162,7 +162,7 @@ static void dce_abm_init(struct abm *abm, uint32_t backlight)
|
|||
BL1_PWM_TARGET_ABM_LEVEL, backlight);
|
||||
|
||||
REG_UPDATE(BL1_PWM_USER_LEVEL,
|
||||
BL1_PWM_USER_LEVEL, backlight);
|
||||
BL1_PWM_USER_LEVEL, user_level);
|
||||
|
||||
REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
|
||||
ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
|
||||
|
|
|
@ -57,9 +57,9 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight)
|
||||
static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight, uint32_t user_level)
|
||||
{
|
||||
dmub_abm_init(abm, backlight);
|
||||
dmub_abm_init(abm, backlight, user_level);
|
||||
}
|
||||
|
||||
static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm)
|
||||
|
|
|
@ -76,10 +76,10 @@ static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
|
|||
cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask;
|
||||
cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
void dmub_abm_init(struct abm *abm, uint32_t backlight)
|
||||
void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
|
||||
{
|
||||
struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
|
||||
|
||||
|
@ -106,7 +106,7 @@ void dmub_abm_init(struct abm *abm, uint32_t backlight)
|
|||
BL1_PWM_TARGET_ABM_LEVEL, backlight);
|
||||
|
||||
REG_UPDATE(BL1_PWM_USER_LEVEL,
|
||||
BL1_PWM_USER_LEVEL, backlight);
|
||||
BL1_PWM_USER_LEVEL, user_level);
|
||||
|
||||
REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
|
||||
ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
|
||||
|
@ -155,7 +155,7 @@ bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask)
|
|||
cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask;
|
||||
cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ void dmub_abm_init_config(struct abm *abm,
|
|||
|
||||
cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, un
|
|||
cmd.abm_pause.abm_pause_data.panel_mask = panel_mask;
|
||||
cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ bool dmub_abm_save_restore(
|
|||
|
||||
cmd.abm_save_restore.header.payload_bytes = sizeof(struct dmub_rb_cmd_abm_save_restore);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
// Copy iramtable data into local structure
|
||||
memcpy((void *)pData, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes);
|
||||
|
@ -274,7 +274,7 @@ bool dmub_abm_set_pipe(struct abm *abm,
|
|||
cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
|
||||
cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ bool dmub_abm_set_backlight_level(struct abm *abm,
|
|||
cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst);
|
||||
cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
struct abm_save_restore;
|
||||
|
||||
void dmub_abm_init(struct abm *abm, uint32_t backlight);
|
||||
void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level);
|
||||
bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask);
|
||||
unsigned int dmub_abm_get_current_backlight(struct abm *abm);
|
||||
unsigned int dmub_abm_get_target_backlight(struct abm *abm);
|
||||
|
|
|
@ -47,7 +47,7 @@ void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
|
|||
if (!lock)
|
||||
cmd.lock_hw.lock_hw_data.should_release = 1;
|
||||
|
||||
dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
|
||||
|
|
|
@ -48,5 +48,5 @@ void dmub_enable_outbox_notification(struct dc_dmub_srv *dmub_srv)
|
|||
sizeof(cmd.outbox1_enable.header);
|
||||
cmd.outbox1_enable.enable = true;
|
||||
|
||||
dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
|
|
@ -105,23 +105,18 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state)
|
|||
*/
|
||||
static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst)
|
||||
{
|
||||
struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
|
||||
uint32_t raw_state = 0;
|
||||
uint32_t retry_count = 0;
|
||||
enum dmub_status status;
|
||||
|
||||
do {
|
||||
// Send gpint command and wait for ack
|
||||
status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30);
|
||||
|
||||
if (status == DMUB_STATUS_OK) {
|
||||
// GPINT was executed, get response
|
||||
dmub_srv_get_gpint_response(srv, &raw_state);
|
||||
if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state,
|
||||
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
|
||||
*state = convert_psr_state(raw_state);
|
||||
} else
|
||||
} else {
|
||||
// Return invalid state when GPINT times out
|
||||
*state = PSR_STATE_INVALID;
|
||||
|
||||
}
|
||||
} while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
|
||||
|
||||
// Assert if max retry hit
|
||||
|
@ -171,7 +166,7 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *
|
|||
cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst;
|
||||
cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -199,7 +194,7 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8
|
|||
|
||||
cmd.psr_enable.header.payload_bytes = 0; // Send header only
|
||||
|
||||
dm_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
/* Below loops 1000 x 500us = 500 ms.
|
||||
* Exit PSR may need to wait 1-2 frames to power up. Timeout after at
|
||||
|
@ -248,7 +243,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_
|
|||
cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
|
||||
cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
|
||||
cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -267,7 +262,7 @@ static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub,
|
|||
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle;
|
||||
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su;
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -286,7 +281,7 @@ static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt
|
|||
cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt;
|
||||
cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst;
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -423,7 +418,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
|
|||
copy_settings_data->relock_delay_frame_cnt = 2;
|
||||
copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height;
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -444,7 +439,7 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
|
|||
cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
|
||||
cmd.psr_enable.header.payload_bytes = 0;
|
||||
|
||||
dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -452,13 +447,11 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
|
|||
*/
|
||||
static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst)
|
||||
{
|
||||
struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub;
|
||||
uint16_t param = (uint16_t)(panel_inst << 8);
|
||||
|
||||
/* Send gpint command and wait for ack */
|
||||
dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, param, 30);
|
||||
|
||||
dmub_srv_get_gpint_response(srv, residency);
|
||||
dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency,
|
||||
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
|
||||
}
|
||||
|
||||
static const struct dmub_psr_funcs psr_funcs = {
|
||||
|
|
|
@ -258,13 +258,97 @@ static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst,
|
|||
*residency = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set REPLAY power optimization flags and coasting vtotal.
|
||||
*/
|
||||
static void dmub_replay_set_power_opt_and_coasting_vtotal(struct dmub_replay *dmub,
|
||||
unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *dc = dmub->ctx;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.type = DMUB_CMD__REPLAY;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal);
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.power_opt = power_opt;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_power_opt_data.panel_inst = panel_inst;
|
||||
cmd.replay_set_power_opt_and_coasting_vtotal.replay_set_coasting_vtotal_data.coasting_vtotal = coasting_vtotal;
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* send Replay general cmd to DMUB.
|
||||
*/
|
||||
static void dmub_replay_send_cmd(struct dmub_replay *dmub,
|
||||
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element)
|
||||
{
|
||||
union dmub_rb_cmd cmd;
|
||||
struct dc_context *ctx = NULL;
|
||||
|
||||
if (dmub == NULL || cmd_element == NULL)
|
||||
return;
|
||||
|
||||
ctx = dmub->ctx;
|
||||
if (ctx != NULL) {
|
||||
|
||||
if (msg != Replay_Msg_Not_Support) {
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
//Header
|
||||
cmd.replay_set_timing_sync.header.type = DMUB_CMD__REPLAY;
|
||||
} else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
|
||||
switch (msg) {
|
||||
case Replay_Set_Timing_Sync_Supported:
|
||||
//Header
|
||||
cmd.replay_set_timing_sync.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED;
|
||||
cmd.replay_set_timing_sync.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_timing_sync);
|
||||
//Cmd Body
|
||||
cmd.replay_set_timing_sync.replay_set_timing_sync_data.panel_inst =
|
||||
cmd_element->sync_data.panel_inst;
|
||||
cmd.replay_set_timing_sync.replay_set_timing_sync_data.timing_sync_supported =
|
||||
cmd_element->sync_data.timing_sync_supported;
|
||||
break;
|
||||
case Replay_Set_Residency_Frameupdate_Timer:
|
||||
//Header
|
||||
cmd.replay_set_frameupdate_timer.header.sub_type =
|
||||
DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER;
|
||||
cmd.replay_set_frameupdate_timer.header.payload_bytes =
|
||||
sizeof(struct dmub_rb_cmd_replay_set_frameupdate_timer);
|
||||
//Cmd Body
|
||||
cmd.replay_set_frameupdate_timer.data.panel_inst =
|
||||
cmd_element->panel_inst;
|
||||
cmd.replay_set_frameupdate_timer.data.enable =
|
||||
cmd_element->timer_data.enable;
|
||||
cmd.replay_set_frameupdate_timer.data.frameupdate_count =
|
||||
cmd_element->timer_data.frameupdate_count;
|
||||
break;
|
||||
case Replay_Msg_Not_Support:
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static const struct dmub_replay_funcs replay_funcs = {
|
||||
.replay_copy_settings = dmub_replay_copy_settings,
|
||||
.replay_enable = dmub_replay_enable,
|
||||
.replay_get_state = dmub_replay_get_state,
|
||||
.replay_set_power_opt = dmub_replay_set_power_opt,
|
||||
.replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal,
|
||||
.replay_residency = dmub_replay_residency,
|
||||
.replay_copy_settings = dmub_replay_copy_settings,
|
||||
.replay_enable = dmub_replay_enable,
|
||||
.replay_get_state = dmub_replay_get_state,
|
||||
.replay_set_power_opt = dmub_replay_set_power_opt,
|
||||
.replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal,
|
||||
.replay_residency = dmub_replay_residency,
|
||||
.replay_set_power_opt_and_coasting_vtotal = dmub_replay_set_power_opt_and_coasting_vtotal,
|
||||
.replay_send_cmd = dmub_replay_send_cmd,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,6 +51,8 @@ struct dmub_replay_funcs {
|
|||
uint8_t panel_inst);
|
||||
void (*replay_residency)(struct dmub_replay *dmub,
|
||||
uint8_t panel_inst, uint32_t *residency, const bool is_start, const bool is_alpm);
|
||||
void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub,
|
||||
unsigned int power_opt, uint8_t panel_inst, uint16_t coasting_vtotal);
|
||||
};
|
||||
|
||||
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#
|
||||
# Makefile for DCN.
|
||||
|
||||
DCN10 = dcn10_init.o dcn10_ipp.o \
|
||||
DCN10 = dcn10_ipp.o \
|
||||
dcn10_hw_sequencer_debug.o \
|
||||
dcn10_dpp.o dcn10_opp.o \
|
||||
dcn10_hubp.o dcn10_mpc.o \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Makefile for DCN.
|
||||
|
||||
DCN20 = dcn20_init.o dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \
|
||||
DCN20 = dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \
|
||||
dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_mmhubbub.o \
|
||||
dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \
|
||||
dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Makefile for DCN.
|
||||
DCN201 = dcn201_init.o \
|
||||
dcn201_hubbub.o\
|
||||
DCN201 = dcn201_hubbub.o\
|
||||
dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_dpp.o \
|
||||
dcn201_dccg.o dcn201_link_encoder.o
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Makefile for DCN21.
|
||||
|
||||
DCN21 = dcn21_init.o dcn21_hubp.o dcn21_hubbub.o \
|
||||
DCN21 = dcn21_hubp.o dcn21_hubbub.o \
|
||||
dcn21_link_encoder.o dcn21_dccg.o
|
||||
|
||||
AMD_DAL_DCN21 = $(addprefix $(AMDDALPATH)/dc/dcn21/,$(DCN21))
|
||||
|
|
|
@ -691,7 +691,7 @@ static void dmcub_PLAT_54186_wa(struct hubp *hubp,
|
|||
cmd.PLAT_54186_wa.flip.flip_params.vmid = flip_regs->vmid;
|
||||
|
||||
PERF_TRACE(); // TODO: remove after performance is stable.
|
||||
dm_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
PERF_TRACE(); // TODO: remove after performance is stable.
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,7 @@
|
|||
#
|
||||
#
|
||||
|
||||
DCN30 := \
|
||||
dcn30_init.o \
|
||||
dcn30_hubbub.o \
|
||||
DCN30 := dcn30_hubbub.o \
|
||||
dcn30_hubp.o \
|
||||
dcn30_dpp.o \
|
||||
dcn30_dccg.o \
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# Makefile for dcn30.
|
||||
|
||||
DCN301 = dcn301_init.o dcn301_dccg.o \
|
||||
DCN301 = dcn301_dccg.o \
|
||||
dcn301_dio_link_encoder.o dcn301_panel_cntl.o dcn301_hubbub.o
|
||||
|
||||
AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#
|
||||
# (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved
|
||||
#
|
||||
# Authors: AMD
|
||||
#
|
||||
# Makefile for dcn302.
|
||||
|
||||
DCN3_02 = dcn302_init.o
|
||||
|
||||
AMD_DAL_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/dcn302/,$(DCN3_02))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_02)
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# Makefile for dcn31.
|
||||
|
||||
DCN31 = dcn31_hubbub.o dcn31_init.o dcn31_hubp.o \
|
||||
DCN31 = dcn31_hubbub.o dcn31_hubp.o \
|
||||
dcn31_dccg.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \
|
||||
dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \
|
||||
dcn31_afmt.o dcn31_vpg.o
|
||||
|
|
|
@ -125,7 +125,7 @@ static bool query_dp_alt_from_dmub(struct link_encoder *enc,
|
|||
cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data);
|
||||
cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
|
||||
|
||||
if (!dm_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -436,7 +436,7 @@ static bool link_dpia_control(struct dc_context *dc_ctx,
|
|||
|
||||
cmd.dig1_dpia_control.dpia_control = *dpia_control;
|
||||
|
||||
dm_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ static bool dcn31_query_backlight_info(struct panel_cntl *panel_cntl, union dmub
|
|||
cmd->panel_cntl.header.payload_bytes = sizeof(cmd->panel_cntl.data);
|
||||
cmd->panel_cntl.data.pwrseq_inst = dcn31_panel_cntl->base.pwrseq_inst;
|
||||
|
||||
return dm_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
|
||||
return dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
|
||||
}
|
||||
|
||||
static uint32_t dcn31_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl)
|
||||
|
@ -85,7 +85,7 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl)
|
|||
panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
|
||||
cmd.panel_cntl.data.bl_pwm_ref_div2 =
|
||||
panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2;
|
||||
if (!dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
if (!dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
|
||||
return 0;
|
||||
|
||||
panel_cntl->stored_backlight_registers.BL_PWM_CNTL = cmd.panel_cntl.data.bl_pwm_cntl;
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
#
|
||||
# Makefile for dcn314.
|
||||
|
||||
DCN314 = dcn314_init.o \
|
||||
dcn314_dio_stream_encoder.o dcn314_dccg.o
|
||||
DCN314 = dcn314_dio_stream_encoder.o dcn314_dccg.o
|
||||
|
||||
AMD_DAL_DCN314 = $(addprefix $(AMDDALPATH)/dc/dcn314/,$(DCN314))
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# Makefile for dcn32.
|
||||
|
||||
DCN32 = dcn32_hubbub.o dcn32_init.o dcn32_dccg.o \
|
||||
DCN32 = dcn32_hubbub.o dcn32_dccg.o \
|
||||
dcn32_mmhubbub.o dcn32_dpp.o dcn32_hubp.o dcn32_mpc.o \
|
||||
dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_resource_helpers.o \
|
||||
dcn32_hpo_dp_link_encoder.o
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dcn20/dcn20_resource.h"
|
||||
#include "dml/dcn32/display_mode_vba_util_32.h"
|
||||
#include "dml/dcn32/dcn32_fpu.h"
|
||||
#include "dc_state_priv.h"
|
||||
|
||||
static bool is_dual_plane(enum surface_pixel_format format)
|
||||
{
|
||||
|
@ -182,20 +183,6 @@ bool dcn32_all_pipes_have_stream_and_plane(struct dc *dc,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool dcn32_subvp_in_use(struct dc *dc,
|
||||
struct dc_state *context)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dcn32_mpo_in_use(struct dc_state *context)
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -264,18 +251,17 @@ static void override_det_for_subvp(struct dc *dc, struct dc_state *context, uint
|
|||
|
||||
// Do not override if a stream has multiple planes
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
if (context->stream_status[i].plane_count > 1) {
|
||||
if (context->stream_status[i].plane_count > 1)
|
||||
return;
|
||||
}
|
||||
if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM) {
|
||||
|
||||
if (dc_state_get_stream_subvp_type(context, context->streams[i]) != SUBVP_PHANTOM)
|
||||
stream_count++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
|
||||
if (pipe_ctx->stream && pipe_ctx->plane_state && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
|
||||
if (dcn32_allow_subvp_high_refresh_rate(dc, context, pipe_ctx)) {
|
||||
|
||||
if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) {
|
||||
|
@ -290,7 +276,7 @@ static void override_det_for_subvp(struct dc *dc, struct dc_state *context, uint
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->stream && pipe_ctx->plane_state && pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
|
||||
if (pipe_ctx->stream && pipe_ctx->plane_state && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
|
||||
if (pipe_ctx->stream->timing.v_addressable == 1080 && pipe_ctx->stream->timing.h_addressable == 1920) {
|
||||
if (pipe_segments[i] > 4)
|
||||
pipe_segments[i] = 4;
|
||||
|
@ -337,14 +323,14 @@ void dcn32_determine_det_override(struct dc *dc,
|
|||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
/* Don't count SubVP streams for DET allocation */
|
||||
if (context->streams[i]->mall_stream_config.type != SUBVP_PHANTOM)
|
||||
if (dc_state_get_stream_subvp_type(context, context->streams[i]) != SUBVP_PHANTOM)
|
||||
stream_count++;
|
||||
}
|
||||
|
||||
if (stream_count > 0) {
|
||||
stream_segments = 18 / stream_count;
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
if (context->streams[i]->mall_stream_config.type == SUBVP_PHANTOM)
|
||||
if (dc_state_get_stream_subvp_type(context, context->streams[i]) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
if (context->stream_status[i].plane_count > 0)
|
||||
|
@ -430,71 +416,6 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
|
|||
dcn32_determine_det_override(dc, context, pipes);
|
||||
}
|
||||
|
||||
/**
|
||||
* dcn32_save_mall_state(): Save MALL (SubVP) state for fast validation cases
|
||||
*
|
||||
* This function saves the MALL (SubVP) case for fast validation cases. For fast validation,
|
||||
* there are situations where a shallow copy of the dc->current_state is created for the
|
||||
* validation. In this case we want to save and restore the mall config because we always
|
||||
* teardown subvp at the beginning of validation (and don't attempt to add it back if it's
|
||||
* fast validation). If we don't restore the subvp config in cases of fast validation +
|
||||
* shallow copy of the dc->current_state, the dc->current_state will have a partially
|
||||
* removed subvp state when we did not intend to remove it.
|
||||
*
|
||||
* NOTE: This function ONLY works if the streams are not moved to a different pipe in the
|
||||
* validation. We don't expect this to happen in fast_validation=1 cases.
|
||||
*
|
||||
* @dc: Current DC state
|
||||
* @context: New DC state to be programmed
|
||||
* @temp_config: struct used to cache the existing MALL state
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void dcn32_save_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream)
|
||||
temp_config->mall_stream_config[i] = pipe->stream->mall_stream_config;
|
||||
|
||||
if (pipe->plane_state)
|
||||
temp_config->is_phantom_plane[i] = pipe->plane_state->is_phantom;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dcn32_restore_mall_state(): Restore MALL (SubVP) state for fast validation cases
|
||||
*
|
||||
* Restore the MALL state based on the previously saved state from dcn32_save_mall_state
|
||||
*
|
||||
* @dc: Current DC state
|
||||
* @context: New DC state to be programmed, restore MALL state into here
|
||||
* @temp_config: struct that has the cached MALL state
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void dcn32_restore_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream)
|
||||
pipe->stream->mall_stream_config = temp_config->mall_stream_config[i];
|
||||
|
||||
if (pipe->plane_state)
|
||||
pipe->plane_state->is_phantom = temp_config->is_phantom_plane[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_STRETCHED_V_BLANK 1000 // in micro-seconds (must ensure to match value in FW)
|
||||
/*
|
||||
* Scaling factor for v_blank stretch calculations considering timing in
|
||||
|
@ -589,13 +510,14 @@ static int get_refresh_rate(struct dc_stream_state *fpo_candidate_stream)
|
|||
*
|
||||
* Return: Pointer to FPO stream candidate if config can support FPO, otherwise NULL
|
||||
*/
|
||||
struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context)
|
||||
struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
int refresh_rate = 0;
|
||||
const int minimum_refreshrate_supported = 120;
|
||||
struct dc_stream_state *fpo_candidate_stream = NULL;
|
||||
bool is_fpo_vactive = false;
|
||||
uint32_t fpo_vactive_margin_us = 0;
|
||||
struct dc_stream_status *fpo_stream_status = NULL;
|
||||
|
||||
if (context == NULL)
|
||||
return NULL;
|
||||
|
@ -618,16 +540,28 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
|
|||
DC_FP_START();
|
||||
dcn32_assign_fpo_vactive_candidate(dc, context, &fpo_candidate_stream);
|
||||
DC_FP_END();
|
||||
|
||||
if (fpo_candidate_stream)
|
||||
fpo_stream_status = dc_state_get_stream_status(context, fpo_candidate_stream);
|
||||
DC_FP_START();
|
||||
is_fpo_vactive = dcn32_find_vactive_pipe(dc, context, dc->debug.fpo_vactive_min_active_margin_us);
|
||||
DC_FP_END();
|
||||
if (!is_fpo_vactive || dc->debug.disable_fpo_vactive)
|
||||
return NULL;
|
||||
} else
|
||||
} else {
|
||||
fpo_candidate_stream = context->streams[0];
|
||||
if (fpo_candidate_stream)
|
||||
fpo_stream_status = dc_state_get_stream_status(context, fpo_candidate_stream);
|
||||
}
|
||||
|
||||
if (!fpo_candidate_stream)
|
||||
/* In DCN32/321, FPO uses per-pipe P-State force.
|
||||
* If there's no planes, HUBP is power gated and
|
||||
* therefore programming UCLK_PSTATE_FORCE does
|
||||
* nothing (P-State will always be asserted naturally
|
||||
* on a pipe that has HUBP power gated. Therefore we
|
||||
* only want to enable FPO if the FPO pipe has both
|
||||
* a stream and a plane.
|
||||
*/
|
||||
if (!fpo_candidate_stream || !fpo_stream_status || fpo_stream_status->plane_count == 0)
|
||||
return NULL;
|
||||
|
||||
if (fpo_candidate_stream->sink->edid_caps.panel_patch.disable_fams)
|
||||
|
@ -716,10 +650,11 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context)
|
|||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe);
|
||||
|
||||
if (resource_is_pipe_type(pipe, OPP_HEAD) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE)) {
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
if (pipe_mall_type == SUBVP_MAIN) {
|
||||
subvp_count++;
|
||||
|
||||
subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe);
|
||||
|
@ -728,7 +663,7 @@ bool dcn32_subvp_drr_admissable(struct dc *dc, struct dc_state *context)
|
|||
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
|
||||
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total);
|
||||
}
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
if (pipe_mall_type == SUBVP_NONE) {
|
||||
non_subvp_pipes++;
|
||||
drr_psr_capable = (drr_psr_capable || dcn32_is_psr_capable(pipe));
|
||||
if (pipe->stream->ignore_msa_timing_param &&
|
||||
|
@ -776,10 +711,11 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
|
|||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe);
|
||||
|
||||
if (resource_is_pipe_type(pipe, OPP_HEAD) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE)) {
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
if (pipe_mall_type == SUBVP_MAIN) {
|
||||
subvp_count++;
|
||||
|
||||
subvp_disallow |= disallow_subvp_in_active_plus_blank(pipe);
|
||||
|
@ -788,7 +724,7 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
|
|||
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
|
||||
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.h_total);
|
||||
}
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
if (pipe_mall_type == SUBVP_NONE) {
|
||||
non_subvp_pipes++;
|
||||
vblank_psr_capable = (vblank_psr_capable || dcn32_is_psr_capable(pipe));
|
||||
if (pipe->stream->ignore_msa_timing_param &&
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# Makefile for DCN35.
|
||||
|
||||
DCN35 = dcn35_init.o dcn35_dio_stream_encoder.o \
|
||||
DCN35 = dcn35_dio_stream_encoder.o \
|
||||
dcn35_dio_link_encoder.o dcn35_dccg.o \
|
||||
dcn35_hubp.o dcn35_hubbub.o \
|
||||
dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o
|
||||
|
|
|
@ -256,6 +256,10 @@ void dcn35_link_encoder_construct(
|
|||
enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
|
||||
enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
|
||||
if (bp_cap_info.DP_IS_USB_C) {
|
||||
/*BIOS not switch to use CONNECTOR_ID_USBC = 24 yet*/
|
||||
enc10->base.features.flags.bits.DP_IS_USB_C = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
|
||||
|
@ -264,4 +268,5 @@ void dcn35_link_encoder_construct(
|
|||
}
|
||||
if (enc10->base.ctx->dc->debug.hdmi20_disable)
|
||||
enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "link.h"
|
||||
#include "dcn20_fpu.h"
|
||||
#include "dc_state_priv.h"
|
||||
|
||||
#define DC_LOGGER \
|
||||
dc->ctx->logger
|
||||
|
@ -440,7 +441,115 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {
|
|||
.use_urgent_burst_bw = 0
|
||||
};
|
||||
|
||||
struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 };
|
||||
struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = {
|
||||
.clock_limits = {
|
||||
{
|
||||
.state = 0,
|
||||
.dcfclk_mhz = 560.0,
|
||||
.fabricclk_mhz = 560.0,
|
||||
.dispclk_mhz = 513.0,
|
||||
.dppclk_mhz = 513.0,
|
||||
.phyclk_mhz = 540.0,
|
||||
.socclk_mhz = 560.0,
|
||||
.dscclk_mhz = 171.0,
|
||||
.dram_speed_mts = 1069.0,
|
||||
},
|
||||
{
|
||||
.state = 1,
|
||||
.dcfclk_mhz = 694.0,
|
||||
.fabricclk_mhz = 694.0,
|
||||
.dispclk_mhz = 642.0,
|
||||
.dppclk_mhz = 642.0,
|
||||
.phyclk_mhz = 600.0,
|
||||
.socclk_mhz = 694.0,
|
||||
.dscclk_mhz = 214.0,
|
||||
.dram_speed_mts = 1324.0,
|
||||
},
|
||||
{
|
||||
.state = 2,
|
||||
.dcfclk_mhz = 875.0,
|
||||
.fabricclk_mhz = 875.0,
|
||||
.dispclk_mhz = 734.0,
|
||||
.dppclk_mhz = 734.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
.socclk_mhz = 875.0,
|
||||
.dscclk_mhz = 245.0,
|
||||
.dram_speed_mts = 1670.0,
|
||||
},
|
||||
{
|
||||
.state = 3,
|
||||
.dcfclk_mhz = 1000.0,
|
||||
.fabricclk_mhz = 1000.0,
|
||||
.dispclk_mhz = 1100.0,
|
||||
.dppclk_mhz = 1100.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
.socclk_mhz = 1000.0,
|
||||
.dscclk_mhz = 367.0,
|
||||
.dram_speed_mts = 2000.0,
|
||||
},
|
||||
{
|
||||
.state = 4,
|
||||
.dcfclk_mhz = 1200.0,
|
||||
.fabricclk_mhz = 1200.0,
|
||||
.dispclk_mhz = 1284.0,
|
||||
.dppclk_mhz = 1284.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
.socclk_mhz = 1200.0,
|
||||
.dscclk_mhz = 428.0,
|
||||
.dram_speed_mts = 2000.0,
|
||||
},
|
||||
{
|
||||
.state = 5,
|
||||
.dcfclk_mhz = 1200.0,
|
||||
.fabricclk_mhz = 1200.0,
|
||||
.dispclk_mhz = 1284.0,
|
||||
.dppclk_mhz = 1284.0,
|
||||
.phyclk_mhz = 810.0,
|
||||
.socclk_mhz = 1200.0,
|
||||
.dscclk_mhz = 428.0,
|
||||
.dram_speed_mts = 2000.0,
|
||||
},
|
||||
},
|
||||
|
||||
.num_states = 5,
|
||||
.sr_exit_time_us = 1.9,
|
||||
.sr_enter_plus_exit_time_us = 4.4,
|
||||
.urgent_latency_us = 3.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 = 40.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
|
||||
.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
|
||||
.max_avg_sdp_bw_use_normal_percent = 40.0,
|
||||
.max_avg_dram_bw_use_normal_percent = 40.0,
|
||||
.writeback_latency_us = 12.0,
|
||||
.ideal_dram_bw_after_urgent_percent = 40.0,
|
||||
.max_request_size_bytes = 256,
|
||||
.dram_channel_width_bytes = 16,
|
||||
.fabric_datapath_to_dcn_data_return_bytes = 64,
|
||||
.dcn_downspread_percent = 0.5,
|
||||
.downspread_percent = 0.5,
|
||||
.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 = 131,
|
||||
.urgent_out_of_order_return_per_channel_bytes = 4096,
|
||||
.channel_interleave_bytes = 256,
|
||||
.num_banks = 8,
|
||||
.num_chans = 16,
|
||||
.vmm_page_size_bytes = 4096,
|
||||
.dram_clock_change_latency_us = 45.0,
|
||||
.writeback_dram_clock_change_latency_us = 23.0,
|
||||
.return_bus_width_bytes = 64,
|
||||
.dispclk_dppclk_vco_speed_mhz = 3850,
|
||||
.xfc_bus_transport_time_us = 20,
|
||||
.xfc_xbuf_latency_tolerance_us = 50,
|
||||
.use_urgent_burst_bw = 0,
|
||||
};
|
||||
|
||||
struct _vcs_dpi_ip_params_st dcn2_1_ip = {
|
||||
.odm_capable = 1,
|
||||
|
@ -1074,7 +1183,7 @@ void dcn20_calculate_dlg_params(struct dc *dc,
|
|||
pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
|
||||
if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) {
|
||||
// Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
|
||||
context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
|
||||
context->res_ctx.pipe_ctx[i].unbounded_req = false;
|
||||
|
@ -1424,7 +1533,7 @@ int dcn20_populate_dml_pipes_from_context(struct dc *dc,
|
|||
*/
|
||||
if (res_ctx->pipe_ctx[i].plane_state &&
|
||||
(res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE ||
|
||||
res_ctx->pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM))
|
||||
dc_state_get_pipe_subvp_type(context, &res_ctx->pipe_ctx[i]) == SUBVP_PHANTOM))
|
||||
pipes[pipe_cnt].pipe.src.num_cursors = 0;
|
||||
else
|
||||
pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "clk_mgr/dcn32/dcn32_smu13_driver_if.h"
|
||||
#include "dcn30/dcn30_resource.h"
|
||||
#include "link.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "resource.h"
|
||||
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
|
@ -290,7 +292,7 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
|
|||
|
||||
/* for subvp + DRR case, if subvp pipes are still present we support pstate */
|
||||
if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported &&
|
||||
dcn32_subvp_in_use(dc, context))
|
||||
resource_subvp_in_use(dc, context))
|
||||
vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = temp_clock_change_support;
|
||||
|
||||
if (vlevel < context->bw_ctx.dml.vba.soc.num_states &&
|
||||
|
@ -341,7 +343,7 @@ void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
|
|||
if (!pipe->stream)
|
||||
continue;
|
||||
|
||||
if (pipe->plane_state && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (pipe->plane_state && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
|
||||
pipes[pipe_idx].pipe.dest.vstartup_start =
|
||||
get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
pipes[pipe_idx].pipe.dest.vupdate_offset =
|
||||
|
@ -624,7 +626,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
|
|||
if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
|
||||
!(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
|
||||
(!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_NONE &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE &&
|
||||
(refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) &&
|
||||
!pipe->plane_state->address.tmz_surface &&
|
||||
(vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 ||
|
||||
|
@ -682,7 +684,7 @@ static bool dcn32_enough_pipes_for_subvp(struct dc *dc, struct dc_state *context
|
|||
|
||||
// Find the minimum pipe split count for non SubVP pipes
|
||||
if (resource_is_pipe_type(pipe, OPP_HEAD) &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE) {
|
||||
split_cnt = 0;
|
||||
while (pipe) {
|
||||
split_cnt++;
|
||||
|
@ -735,8 +737,8 @@ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context)
|
|||
* and also to store the two main SubVP pipe pointers in subvp_pipes[2].
|
||||
*/
|
||||
if (pipe->stream && pipe->plane_state && !pipe->top_pipe &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
phantom = pipe->stream->mall_stream_config.paired_stream;
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
|
||||
phantom = dc_state_get_paired_subvp_stream(context, pipe->stream);
|
||||
microschedule_lines = (phantom->timing.v_total - phantom->timing.v_front_porch) +
|
||||
phantom->timing.v_addressable;
|
||||
|
||||
|
@ -804,6 +806,9 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
|
|||
int16_t stretched_drr_us = 0;
|
||||
int16_t drr_stretched_vblank_us = 0;
|
||||
int16_t max_vblank_mallregion = 0;
|
||||
struct dc_stream_state *phantom_stream;
|
||||
bool subvp_found = false;
|
||||
bool drr_found = false;
|
||||
|
||||
// Find SubVP pipe
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
|
@ -816,8 +821,10 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
|
|||
continue;
|
||||
|
||||
// Find the SubVP pipe
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
|
||||
subvp_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the DRR pipe
|
||||
|
@ -825,32 +832,37 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
|
|||
drr_pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
// We check for master pipe only
|
||||
if (!resource_is_pipe_type(pipe, OTG_MASTER) ||
|
||||
!resource_is_pipe_type(pipe, DPP_PIPE))
|
||||
if (!resource_is_pipe_type(drr_pipe, OTG_MASTER) ||
|
||||
!resource_is_pipe_type(drr_pipe, DPP_PIPE))
|
||||
continue;
|
||||
|
||||
if (drr_pipe->stream->mall_stream_config.type == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param &&
|
||||
(drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable || drr_pipe->stream->vrr_active_fixed))
|
||||
if (dc_state_get_pipe_subvp_type(context, drr_pipe) == SUBVP_NONE && drr_pipe->stream->ignore_msa_timing_param &&
|
||||
(drr_pipe->stream->allow_freesync || drr_pipe->stream->vrr_active_variable || drr_pipe->stream->vrr_active_fixed)) {
|
||||
drr_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
main_timing = &pipe->stream->timing;
|
||||
phantom_timing = &pipe->stream->mall_stream_config.paired_stream->timing;
|
||||
drr_timing = &drr_pipe->stream->timing;
|
||||
prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total /
|
||||
(double)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
|
||||
dc->caps.subvp_prefetch_end_to_mall_start_us;
|
||||
subvp_active_us = main_timing->v_addressable * main_timing->h_total /
|
||||
(double)(main_timing->pix_clk_100hz * 100) * 1000000;
|
||||
drr_frame_us = drr_timing->v_total * drr_timing->h_total /
|
||||
(double)(drr_timing->pix_clk_100hz * 100) * 1000000;
|
||||
// P-State allow width and FW delays already included phantom_timing->v_addressable
|
||||
mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total /
|
||||
(double)(phantom_timing->pix_clk_100hz * 100) * 1000000;
|
||||
stretched_drr_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US;
|
||||
drr_stretched_vblank_us = (drr_timing->v_total - drr_timing->v_addressable) * drr_timing->h_total /
|
||||
(double)(drr_timing->pix_clk_100hz * 100) * 1000000 + (stretched_drr_us - drr_frame_us);
|
||||
max_vblank_mallregion = drr_stretched_vblank_us > mall_region_us ? drr_stretched_vblank_us : mall_region_us;
|
||||
if (subvp_found && drr_found) {
|
||||
phantom_stream = dc_state_get_paired_subvp_stream(context, pipe->stream);
|
||||
main_timing = &pipe->stream->timing;
|
||||
phantom_timing = &phantom_stream->timing;
|
||||
drr_timing = &drr_pipe->stream->timing;
|
||||
prefetch_us = (phantom_timing->v_total - phantom_timing->v_front_porch) * phantom_timing->h_total /
|
||||
(double)(phantom_timing->pix_clk_100hz * 100) * 1000000 +
|
||||
dc->caps.subvp_prefetch_end_to_mall_start_us;
|
||||
subvp_active_us = main_timing->v_addressable * main_timing->h_total /
|
||||
(double)(main_timing->pix_clk_100hz * 100) * 1000000;
|
||||
drr_frame_us = drr_timing->v_total * drr_timing->h_total /
|
||||
(double)(drr_timing->pix_clk_100hz * 100) * 1000000;
|
||||
// P-State allow width and FW delays already included phantom_timing->v_addressable
|
||||
mall_region_us = phantom_timing->v_addressable * phantom_timing->h_total /
|
||||
(double)(phantom_timing->pix_clk_100hz * 100) * 1000000;
|
||||
stretched_drr_us = drr_frame_us + mall_region_us + SUBVP_DRR_MARGIN_US;
|
||||
drr_stretched_vblank_us = (drr_timing->v_total - drr_timing->v_addressable) * drr_timing->h_total /
|
||||
(double)(drr_timing->pix_clk_100hz * 100) * 1000000 + (stretched_drr_us - drr_frame_us);
|
||||
max_vblank_mallregion = drr_stretched_vblank_us > mall_region_us ? drr_stretched_vblank_us : mall_region_us;
|
||||
}
|
||||
|
||||
/* We consider SubVP + DRR schedulable if the stretched frame duration of the DRR display (i.e. the
|
||||
* highest refresh rate + margin that can support UCLK P-State switch) passes the static analysis
|
||||
|
@ -895,6 +907,8 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
|
|||
struct dc_crtc_timing *main_timing = NULL;
|
||||
struct dc_crtc_timing *phantom_timing = NULL;
|
||||
struct dc_crtc_timing *vblank_timing = NULL;
|
||||
struct dc_stream_state *phantom_stream;
|
||||
enum mall_stream_type pipe_mall_type;
|
||||
|
||||
/* For SubVP + VBLANK/DRR cases, we assume there can only be
|
||||
* a single VBLANK/DRR display. If DML outputs SubVP + VBLANK
|
||||
|
@ -904,6 +918,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
|
|||
*/
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
pipe = &context->res_ctx.pipe_ctx[i];
|
||||
pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe);
|
||||
|
||||
// We check for master pipe, but it shouldn't matter since we only need
|
||||
// the pipe for timing info (stream should be same for any pipe splits)
|
||||
|
@ -911,18 +926,19 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
|
|||
!resource_is_pipe_type(pipe, DPP_PIPE))
|
||||
continue;
|
||||
|
||||
if (!found && pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
if (!found && pipe_mall_type == SUBVP_NONE) {
|
||||
// Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe).
|
||||
vblank_index = i;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
||||
if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN)
|
||||
subvp_pipe = pipe;
|
||||
}
|
||||
if (found) {
|
||||
phantom_stream = dc_state_get_paired_subvp_stream(context, subvp_pipe->stream);
|
||||
main_timing = &subvp_pipe->stream->timing;
|
||||
phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
|
||||
phantom_timing = &phantom_stream->timing;
|
||||
vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing;
|
||||
// Prefetch time is equal to VACTIVE + BP + VSYNC of the phantom pipe
|
||||
// Also include the prefetch end to mallstart delay time
|
||||
|
@ -977,7 +993,7 @@ static bool subvp_subvp_admissable(struct dc *dc,
|
|||
continue;
|
||||
|
||||
if (pipe->plane_state && !pipe->top_pipe &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN) {
|
||||
refresh_rate = (pipe->stream->timing.pix_clk_100hz * (uint64_t)100 +
|
||||
pipe->stream->timing.v_total * pipe->stream->timing.h_total - (uint64_t)1);
|
||||
refresh_rate = div_u64(refresh_rate, pipe->stream->timing.v_total);
|
||||
|
@ -1026,23 +1042,23 @@ static bool subvp_validate_static_schedulability(struct dc *dc,
|
|||
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
enum mall_stream_type pipe_mall_type = dc_state_get_pipe_subvp_type(context, pipe);
|
||||
|
||||
if (!pipe->stream)
|
||||
continue;
|
||||
|
||||
if (pipe->plane_state && !pipe->top_pipe) {
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
||||
if (pipe_mall_type == SUBVP_MAIN)
|
||||
subvp_count++;
|
||||
if (pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
if (pipe_mall_type == SUBVP_NONE)
|
||||
non_subvp_pipes++;
|
||||
}
|
||||
}
|
||||
|
||||
// Count how many planes that aren't SubVP/phantom are capable of VACTIVE
|
||||
// switching (SubVP + VACTIVE unsupported). In situations where we force
|
||||
// SubVP for a VACTIVE plane, we don't want to increment the vactive_count.
|
||||
if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vlevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 &&
|
||||
pipe->stream->mall_stream_config.type == SUBVP_NONE) {
|
||||
pipe_mall_type == SUBVP_NONE) {
|
||||
vactive_count++;
|
||||
}
|
||||
pipe_idx++;
|
||||
|
@ -1078,7 +1094,7 @@ static void assign_subvp_index(struct dc *dc, struct dc_state *context)
|
|||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) &&
|
||||
pipe_ctx->stream->mall_stream_config.type == SUBVP_MAIN) {
|
||||
dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) {
|
||||
pipe_ctx->subvp_index = index++;
|
||||
} else {
|
||||
pipe_ctx->subvp_index = 0;
|
||||
|
@ -1532,7 +1548,8 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
|
|||
// If SubVP pipe config is unsupported (or cannot be used for UCLK switching)
|
||||
// remove phantom pipes and repopulate dml pipes
|
||||
if (!found_supported_config) {
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported;
|
||||
*pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false);
|
||||
|
||||
|
@ -1684,7 +1701,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
|
|||
pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt,
|
||||
pipe_idx);
|
||||
|
||||
if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
|
||||
if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM) {
|
||||
// Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
|
||||
context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
|
||||
context->res_ctx.pipe_ctx[i].unbounded_req = false;
|
||||
|
@ -1716,7 +1733,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
|
|||
context->res_ctx.pipe_ctx[i].plane_state != context->res_ctx.pipe_ctx[i].top_pipe->plane_state) &&
|
||||
context->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) {
|
||||
/* SS: all active surfaces stored in MALL */
|
||||
if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type != SUBVP_PHANTOM) {
|
||||
if (dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) != SUBVP_PHANTOM) {
|
||||
context->bw_ctx.bw.dcn.mall_ss_size_bytes += context->res_ctx.pipe_ctx[i].surface_size_in_mall_bytes;
|
||||
|
||||
if (context->res_ctx.pipe_ctx[i].stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) {
|
||||
|
@ -1930,7 +1947,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
|
|||
return false;
|
||||
|
||||
// For each full update, remove all existing phantom pipes first
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, fast_validate);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
|
||||
dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
|
||||
|
||||
|
@ -2255,7 +2273,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
|
|||
unsigned int dummy_latency_index = 0;
|
||||
int maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
|
||||
unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
|
||||
bool subvp_in_use = dcn32_subvp_in_use(dc, context);
|
||||
bool subvp_active = resource_subvp_in_use(dc, context);
|
||||
unsigned int min_dram_speed_mts_margin;
|
||||
bool need_fclk_lat_as_dummy = false;
|
||||
bool is_subvp_p_drr = false;
|
||||
|
@ -2264,7 +2282,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
|
|||
dc_assert_fp_enabled();
|
||||
|
||||
/* need to find dummy latency index for subvp */
|
||||
if (subvp_in_use) {
|
||||
if (subvp_active) {
|
||||
/* Override DRAMClockChangeSupport for SubVP + DRR case where the DRR cannot switch without stretching it's VBLANK */
|
||||
if (!pstate_en) {
|
||||
context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp;
|
||||
|
@ -2450,7 +2468,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
|
|||
dc->clk_mgr->bw_params->clk_table.entries[min_dram_speed_mts_offset].memclk_mhz * 16;
|
||||
}
|
||||
|
||||
if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !subvp_in_use) {
|
||||
if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !subvp_active) {
|
||||
/* find largest table entry that is lower than dram speed,
|
||||
* but lower than DPM0 still uses DPM0
|
||||
*/
|
||||
|
@ -3448,7 +3466,15 @@ void dcn32_assign_fpo_vactive_candidate(struct dc *dc, const struct dc_state *co
|
|||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (!pipe->stream)
|
||||
/* In DCN32/321, FPO uses per-pipe P-State force.
|
||||
* If there's no planes, HUBP is power gated and
|
||||
* therefore programming UCLK_PSTATE_FORCE does
|
||||
* nothing (P-State will always be asserted naturally
|
||||
* on a pipe that has HUBP power gated. Therefore we
|
||||
* only want to enable FPO if the FPO pipe has both
|
||||
* a stream and a plane.
|
||||
*/
|
||||
if (!pipe->stream || !pipe->plane_state)
|
||||
continue;
|
||||
|
||||
if (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0) {
|
||||
|
@ -3502,7 +3528,7 @@ void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb)
|
|||
void dcn32_override_min_req_memclk(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
// WA: restrict FPO and SubVP to use first non-strobe mode (DCN32 BW issue)
|
||||
if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dcn32_subvp_in_use(dc, context)) &&
|
||||
if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || resource_subvp_in_use(dc, context)) &&
|
||||
dc->dml.soc.num_chans <= 8) {
|
||||
int num_mclk_levels = dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user