mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:24:45 +01:00
amd-drm-next-6.20-2026-01-23:
amdgpu: - GC 12 fix - UserQ fixes - Misc error path fixes - IP discovery fixes - Misc cleanups - HDMI fixes - Documentation update - Panel replay fixes - Panel type handling fixes - DCN 3.1.x fixes - DC analog display fix - SMU 6 fixes - VCN 4.0.3 queue reset fix - VCN 5.0.1 queue reset fix - GPUVM TLB flush fix - RAS fixes - DC idle optimization fix amdkfd: - MQD fix for GC 9.4.3 and 9.5 - GC 11 cooperative launch fix - GC 12.1 trap handler fixes - Misc cleanups radeon: - Use drm_* logging helpers for VCE -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCaXOwTQAKCRC93/aFa7yZ 2G2JAQCQN5BrBSL1gY3hoGpzG/o5oTjxVqIYJDi3eC02ecAyAQD/RPSkPCKc38E1 Jy7ApjcEoKA6qBCRA1gpKihi+BwS/Ao= =opLX -----END PGP SIGNATURE----- Merge tag 'amd-drm-next-6.20-2026-01-23' of https://gitlab.freedesktop.org/agd5f/linux into drm-next amd-drm-next-6.20-2026-01-23: amdgpu: - GC 12 fix - UserQ fixes - Misc error path fixes - IP discovery fixes - Misc cleanups - HDMI fixes - Documentation update - Panel replay fixes - Panel type handling fixes - DCN 3.1.x fixes - DC analog display fix - SMU 6 fixes - VCN 4.0.3 queue reset fix - VCN 5.0.1 queue reset fix - GPUVM TLB flush fix - RAS fixes - DC idle optimization fix amdkfd: - MQD fix for GC 9.4.3 and 9.5 - GC 11 cooperative launch fix - GC 12.1 trap handler fixes - Misc cleanups radeon: - Use drm_* logging helpers for VCE Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260123173537.17221-1-alexander.deucher@amd.com
This commit is contained in:
commit
504f3cead6
65 changed files with 1440 additions and 1194 deletions
|
|
@ -16,3 +16,6 @@ Ryzen AI 300 series, Strix Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0, 14.0.0
|
|||
Ryzen AI 330 series, Krackan Point, 3.6.0, 11.5.3, 4.0.5, 6.1.3, 14.0.5, 14.0.5
|
||||
Ryzen AI 350 series, Krackan Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4, 14.0.4
|
||||
Ryzen AI Max 300 series, Strix Halo, 3.5.1, 11.5.1, 4.0.6, 6.1.1, 14.0.1, 14.0.1
|
||||
Ryzen AI 9 475 / 470 / 465, Gorgon Point, 3.5.0, 11.5.0, 4.0.5, 6.1.0, 14.0.0, 14.0.0
|
||||
Ryzen AI 7 450, Gorgon Point, 3.5.0, 11.5.2, 4.0.5, 6.1.2, 14.0.4, 14.0.4
|
||||
Ryzen AI 5 440 / 435, Gorgon Point, 3.6.0, 11.5.3, 4.0.5, 6.1.3, 14.0.5, 14.0.5
|
||||
|
|
|
|||
|
|
|
@ -334,7 +334,8 @@ int amdgpu_amdkfd_alloc_kernel_mem(struct amdgpu_device *adev, size_t size,
|
|||
bp.size = size;
|
||||
bp.byte_align = PAGE_SIZE;
|
||||
bp.domain = domain;
|
||||
bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
|
|
|||
|
|
@ -380,10 +380,21 @@ static uint16_t amdgpu_discovery_calculate_checksum(uint8_t *data, uint32_t size
|
|||
return checksum;
|
||||
}
|
||||
|
||||
static inline bool amdgpu_discovery_verify_checksum(uint8_t *data, uint32_t size,
|
||||
static inline bool amdgpu_discovery_verify_checksum(struct amdgpu_device *adev,
|
||||
uint8_t *data, uint32_t size,
|
||||
uint16_t expected)
|
||||
{
|
||||
return !!(amdgpu_discovery_calculate_checksum(data, size) == expected);
|
||||
uint16_t calculated;
|
||||
|
||||
calculated = amdgpu_discovery_calculate_checksum(data, size);
|
||||
|
||||
if (calculated != expected) {
|
||||
dev_err(adev->dev, "Discovery checksum failed: calc 0x%04x != exp 0x%04x, size %u.\n",
|
||||
calculated, expected, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary)
|
||||
|
|
@ -439,7 +450,7 @@ static int amdgpu_discovery_verify_npsinfo(struct amdgpu_device *adev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
le32_to_cpu(nhdr->size_bytes),
|
||||
checksum)) {
|
||||
dev_dbg(adev->dev, "invalid nps info data table checksum\n");
|
||||
|
|
@ -529,7 +540,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
size = le16_to_cpu(bhdr->binary_size) - offset;
|
||||
checksum = le16_to_cpu(bhdr->binary_checksum);
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset, size,
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset, size,
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "invalid ip discovery binary checksum\n");
|
||||
r = -EINVAL;
|
||||
|
|
@ -549,7 +560,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
le16_to_cpu(ihdr->size),
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "invalid ip discovery data table checksum\n");
|
||||
|
|
@ -572,7 +583,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(discovery_bin + offset,
|
||||
if (!amdgpu_discovery_verify_checksum(adev, discovery_bin + offset,
|
||||
le32_to_cpu(ghdr->size),
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "invalid gc data table checksum\n");
|
||||
|
|
@ -595,7 +606,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
sizeof(struct harvest_table), checksum)) {
|
||||
dev_err(adev->dev, "invalid harvest data table checksum\n");
|
||||
|
|
@ -618,7 +629,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
le32_to_cpu(vhdr->size_bytes), checksum)) {
|
||||
dev_err(adev->dev, "invalid vcn data table checksum\n");
|
||||
|
|
@ -641,7 +652,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!amdgpu_discovery_verify_checksum(
|
||||
if (!amdgpu_discovery_verify_checksum(adev,
|
||||
discovery_bin + offset,
|
||||
le32_to_cpu(mhdr->size_bytes), checksum)) {
|
||||
dev_err(adev->dev, "invalid mall data table checksum\n");
|
||||
|
|
@ -1867,7 +1878,7 @@ static int amdgpu_discovery_refresh_nps_info(struct amdgpu_device *adev,
|
|||
sizeof(*nps_data), false);
|
||||
|
||||
nhdr = (struct nps_info_header *)(nps_data);
|
||||
if (!amdgpu_discovery_verify_checksum((uint8_t *)nps_data,
|
||||
if (!amdgpu_discovery_verify_checksum(adev, (uint8_t *)nps_data,
|
||||
le32_to_cpu(nhdr->size_bytes),
|
||||
checksum)) {
|
||||
dev_err(adev->dev, "nps data refresh, checksum mismatch\n");
|
||||
|
|
|
|||
|
|
@ -708,12 +708,12 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
|
|||
*/
|
||||
|
||||
/**
|
||||
* amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
|
||||
* amdgpu_fence_driver_update_timedout_fence_state - Update fence state and set errors
|
||||
*
|
||||
* @af: fence of the ring to signal
|
||||
* @af: fence of the ring to update
|
||||
*
|
||||
*/
|
||||
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af)
|
||||
void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af)
|
||||
{
|
||||
struct dma_fence *unprocessed;
|
||||
struct dma_fence __rcu **ptr;
|
||||
|
|
@ -763,7 +763,7 @@ void amdgpu_fence_save_wptr(struct amdgpu_fence *af)
|
|||
}
|
||||
|
||||
static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
|
||||
u64 start_wptr, u32 end_wptr)
|
||||
u64 start_wptr, u64 end_wptr)
|
||||
{
|
||||
unsigned int first_idx = start_wptr & ring->buf_mask;
|
||||
unsigned int last_idx = end_wptr & ring->buf_mask;
|
||||
|
|
|
|||
|
|
@ -1298,7 +1298,8 @@ failed_undo:
|
|||
failed_unlock:
|
||||
spin_unlock_irqrestore(&kiq->ring_lock, flags);
|
||||
failed_kiq_hdp_flush:
|
||||
dev_err(adev->dev, "failed to flush HDP via KIQ\n");
|
||||
if (!amdgpu_in_reset(adev))
|
||||
dev_err(adev->dev, "failed to flush HDP via KIQ\n");
|
||||
return r < 0 ? r : -EIO;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -781,8 +781,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
|
|||
|
||||
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
|
||||
|
||||
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
|
||||
return 0;
|
||||
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) {
|
||||
r = 0;
|
||||
goto error_unlock_reset;
|
||||
}
|
||||
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
|
|||
if (job && job->vmid)
|
||||
amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
|
||||
amdgpu_ring_undo(ring);
|
||||
return r;
|
||||
goto free_fence;
|
||||
}
|
||||
*f = &af->base;
|
||||
/* get a ref for the job */
|
||||
|
|
|
|||
|
|
@ -218,8 +218,11 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
if (!entity)
|
||||
return 0;
|
||||
|
||||
return drm_sched_job_init(&(*job)->base, entity, 1, owner,
|
||||
drm_client_id);
|
||||
r = drm_sched_job_init(&(*job)->base, entity, 1, owner, drm_client_id);
|
||||
if (!r)
|
||||
return 0;
|
||||
|
||||
kfree((*job)->hw_vm_fence);
|
||||
|
||||
err_fence:
|
||||
kfree((*job)->hw_fence);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ enum amdgpu_ib_pool_type;
|
|||
#define AMDGPU_KERNEL_JOB_ID_FLUSH_GPU_TLB (18446744073709551604ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_KFD_GART_MAP (18446744073709551603ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_VCN_RING_TEST (18446744073709551602ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_GFX_RING_TEST (18446744073709551601ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_SDMA_RING_TEST (18446744073709551600ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_VPE_RING_TEST (18446744073709551599ULL)
|
||||
#define AMDGPU_KERNEL_JOB_ID_RUN_SHADER (18446744073709551598ULL)
|
||||
|
||||
struct amdgpu_job {
|
||||
struct drm_sched_job base;
|
||||
|
|
|
|||
|
|
@ -2784,6 +2784,10 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev,
|
|||
if (!data->bps[i].ts)
|
||||
continue;
|
||||
|
||||
/* U64_MAX is used to mark the record as invalid */
|
||||
if (data->bps[i].retired_page == U64_MAX)
|
||||
continue;
|
||||
|
||||
bps[r].bp = data->bps[i].retired_page;
|
||||
r++;
|
||||
if (r >= count)
|
||||
|
|
@ -3090,6 +3094,8 @@ static int __amdgpu_ras_restore_bad_pages(struct amdgpu_device *adev,
|
|||
|
||||
if (amdgpu_ras_check_bad_page_unlock(con,
|
||||
bps[j].retired_page << AMDGPU_GPU_PAGE_SHIFT)) {
|
||||
/* set to U64_MAX to mark it as invalid */
|
||||
data->bps[data->count].retired_page = U64_MAX;
|
||||
data->count++;
|
||||
data->space_left--;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -885,9 +885,9 @@ int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
/* signal the guilty fence and set an error on all fences from the context */
|
||||
/* set an error on all fences from the context */
|
||||
if (guilty_fence)
|
||||
amdgpu_fence_driver_guilty_force_completion(guilty_fence);
|
||||
amdgpu_fence_driver_update_timedout_fence_state(guilty_fence);
|
||||
/* Re-emit the non-guilty commands */
|
||||
if (ring->ring_backup_entries_to_copy) {
|
||||
amdgpu_ring_alloc_reemit(ring, ring->ring_backup_entries_to_copy);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ extern const struct drm_sched_backend_ops amdgpu_sched_ops;
|
|||
|
||||
void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error);
|
||||
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
|
||||
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af);
|
||||
void amdgpu_fence_driver_update_timedout_fence_state(struct amdgpu_fence *af);
|
||||
void amdgpu_fence_save_wptr(struct amdgpu_fence *af);
|
||||
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
|
||||
|
|
|
|||
|
|
@ -148,6 +148,69 @@ amdgpu_userq_detect_and_reset_queues(struct amdgpu_userq_mgr *uq_mgr)
|
|||
return r;
|
||||
}
|
||||
|
||||
static void amdgpu_userq_hang_detect_work(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_usermode_queue *queue = container_of(work,
|
||||
struct amdgpu_usermode_queue,
|
||||
hang_detect_work.work);
|
||||
struct dma_fence *fence;
|
||||
struct amdgpu_userq_mgr *uq_mgr;
|
||||
|
||||
if (!queue || !queue->userq_mgr)
|
||||
return;
|
||||
|
||||
uq_mgr = queue->userq_mgr;
|
||||
fence = READ_ONCE(queue->hang_detect_fence);
|
||||
/* Fence already signaled – no action needed */
|
||||
if (!fence || dma_fence_is_signaled(fence))
|
||||
return;
|
||||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
amdgpu_userq_detect_and_reset_queues(uq_mgr);
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start hang detection for a user queue fence. A delayed work will be scheduled
|
||||
* to check if the fence is still pending after the timeout period.
|
||||
*/
|
||||
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
unsigned long timeout_ms;
|
||||
|
||||
if (!queue || !queue->userq_mgr || !queue->userq_mgr->adev)
|
||||
return;
|
||||
|
||||
adev = queue->userq_mgr->adev;
|
||||
/* Determine timeout based on queue type */
|
||||
switch (queue->queue_type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout_ms = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout_ms = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout_ms = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout_ms = adev->gfx_timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store the fence to monitor and schedule hang detection */
|
||||
WRITE_ONCE(queue->hang_detect_fence, queue->last_fence);
|
||||
schedule_delayed_work(&queue->hang_detect_work,
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
}
|
||||
|
||||
static void amdgpu_userq_init_hang_detect_work(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
INIT_DELAYED_WORK(&queue->hang_detect_work, amdgpu_userq_hang_detect_work);
|
||||
queue->hang_detect_fence = NULL;
|
||||
}
|
||||
|
||||
static int amdgpu_userq_buffer_va_list_add(struct amdgpu_usermode_queue *queue,
|
||||
struct amdgpu_bo_va_mapping *va_map, u64 addr)
|
||||
{
|
||||
|
|
@ -572,7 +635,6 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
|
|||
|
||||
cancel_delayed_work_sync(&uq_mgr->resume_work);
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
|
||||
queue = amdgpu_userq_find(uq_mgr, queue_id);
|
||||
if (!queue) {
|
||||
drm_dbg_driver(adev_to_drm(uq_mgr->adev), "Invalid queue id to destroy\n");
|
||||
|
|
@ -580,6 +642,11 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
|
|||
return -EINVAL;
|
||||
}
|
||||
amdgpu_userq_wait_for_last_fence(queue);
|
||||
/* Cancel any pending hang detection work and cleanup */
|
||||
if (queue->hang_detect_fence) {
|
||||
cancel_delayed_work_sync(&queue->hang_detect_work);
|
||||
queue->hang_detect_fence = NULL;
|
||||
}
|
||||
r = amdgpu_bo_reserve(queue->db_obj.obj, true);
|
||||
if (!r) {
|
||||
amdgpu_bo_unpin(queue->db_obj.obj);
|
||||
|
|
@ -819,6 +886,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
queue->debugfs_queue = debugfs_create_dir(queue_name, filp->debugfs_client);
|
||||
debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);
|
||||
#endif
|
||||
amdgpu_userq_init_hang_detect_work(queue);
|
||||
kfree(queue_name);
|
||||
|
||||
args->out.queue_id = qid;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ struct amdgpu_usermode_queue {
|
|||
u32 xcp_id;
|
||||
int priority;
|
||||
struct dentry *debugfs_queue;
|
||||
struct delayed_work hang_detect_work;
|
||||
struct dma_fence *hang_detect_fence;
|
||||
|
||||
struct list_head userq_va_list;
|
||||
};
|
||||
|
|
@ -147,6 +149,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
|
|||
void amdgpu_userq_reset_work(struct work_struct *work);
|
||||
void amdgpu_userq_pre_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost);
|
||||
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue);
|
||||
|
||||
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_usermode_queue *queue,
|
||||
|
|
|
|||
|
|
@ -574,6 +574,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
dma_fence_put(queue->last_fence);
|
||||
queue->last_fence = dma_fence_get(fence);
|
||||
amdgpu_userq_start_hang_detect_work(queue);
|
||||
mutex_unlock(&userq_mgr->userq_mutex);
|
||||
|
||||
drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT,
|
||||
|
|
|
|||
|
|
@ -278,7 +278,6 @@ static void gfx_v12_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
|
|||
u32 sh_num, u32 instance, int xcc_id);
|
||||
static u32 gfx_v12_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
|
||||
|
||||
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start, bool secure);
|
||||
static void gfx_v12_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t val);
|
||||
static int gfx_v12_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev);
|
||||
|
|
@ -4629,16 +4628,6 @@ static int gfx_v12_0_ring_preempt_ib(struct amdgpu_ring *ring)
|
|||
return r;
|
||||
}
|
||||
|
||||
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring,
|
||||
bool start,
|
||||
bool secure)
|
||||
{
|
||||
uint32_t v = secure ? FRAME_TMZ : 0;
|
||||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0));
|
||||
amdgpu_ring_write(ring, v | FRAME_CMD(start ? 0 : 1));
|
||||
}
|
||||
|
||||
static void gfx_v12_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
|
||||
uint32_t reg_val_offs)
|
||||
{
|
||||
|
|
@ -5515,7 +5504,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
|
|||
.emit_cntxcntl = gfx_v12_0_ring_emit_cntxcntl,
|
||||
.init_cond_exec = gfx_v12_0_ring_emit_init_cond_exec,
|
||||
.preempt_ib = gfx_v12_0_ring_preempt_ib,
|
||||
.emit_frame_cntl = gfx_v12_0_ring_emit_frame_cntl,
|
||||
.emit_wreg = gfx_v12_0_ring_emit_wreg,
|
||||
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
|
||||
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
|
||||
|
|
|
|||
|
|
@ -1145,13 +1145,18 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
|
|||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
if (amdgpu_sriov_vf(ring->adev))
|
||||
return -EOPNOTSUPP;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
|
||||
int r;
|
||||
|
||||
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
|
||||
mutex_lock(&vinst->engine_reset_mutex);
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
jpeg_v4_0_3_core_stall_reset(ring);
|
||||
jpeg_v4_0_3_start_jrbc(ring);
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
mutex_unlock(&vinst->engine_reset_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
|
||||
|
|
|
|||
|
|
@ -844,10 +844,19 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
|
|||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
|
||||
int r;
|
||||
|
||||
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
|
||||
mutex_lock(&vinst->engine_reset_mutex);
|
||||
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
jpeg_v5_0_1_core_stall_reset(ring);
|
||||
jpeg_v5_0_1_init_jrbc(ring);
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
mutex_unlock(&vinst->engine_reset_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
|
||||
|
|
|
|||
|
|
@ -847,6 +847,7 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
|||
int inst_idx = vinst->inst;
|
||||
struct amdgpu_vcn4_fw_shared *fw_shared =
|
||||
adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
|
||||
struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};
|
||||
struct amdgpu_ring *ring;
|
||||
int vcn_inst, ret;
|
||||
uint32_t tmp;
|
||||
|
|
@ -951,6 +952,9 @@ static int vcn_v4_0_3_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
|||
|
||||
ring = &adev->vcn.inst[inst_idx].ring_enc[0];
|
||||
|
||||
/* Pause dpg */
|
||||
vcn_v4_0_3_pause_dpg_mode(vinst, &state);
|
||||
|
||||
/* program the RB_BASE for ring buffer */
|
||||
WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO,
|
||||
lower_32_bits(ring->gpu_addr));
|
||||
|
|
@ -1360,9 +1364,13 @@ static int vcn_v4_0_3_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)
|
|||
int inst_idx = vinst->inst;
|
||||
uint32_t tmp;
|
||||
int vcn_inst;
|
||||
struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
|
||||
|
||||
vcn_inst = GET_INST(VCN, inst_idx);
|
||||
|
||||
/* Unpause dpg */
|
||||
vcn_v4_0_3_pause_dpg_mode(vinst, &state);
|
||||
|
||||
/* Wait for power status to be 1 */
|
||||
SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,
|
||||
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
|
||||
|
|
@ -1486,6 +1494,39 @@ Done:
|
|||
static int vcn_v4_0_3_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
||||
struct dpg_pause_state *new_state)
|
||||
{
|
||||
struct amdgpu_device *adev = vinst->adev;
|
||||
int inst_idx = vinst->inst;
|
||||
uint32_t reg_data = 0;
|
||||
int ret_code;
|
||||
|
||||
/* pause/unpause if state is changed */
|
||||
if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
|
||||
DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
|
||||
adev->vcn.inst[inst_idx].pause_state.fw_based, new_state->fw_based);
|
||||
reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
|
||||
(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
|
||||
|
||||
if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
|
||||
ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
|
||||
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
|
||||
|
||||
if (!ret_code) {
|
||||
/* pause DPG */
|
||||
reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
|
||||
WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
|
||||
|
||||
/* wait for ACK */
|
||||
SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
|
||||
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
|
||||
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
|
||||
}
|
||||
} else {
|
||||
/* unpause dpg, no need to wait */
|
||||
reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
|
||||
WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
|
||||
}
|
||||
adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1596,6 +1637,60 @@ static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
uint32_t wait_seq = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
|
||||
ring = &adev->jpeg.inst[inst].ring_dec[i];
|
||||
|
||||
drm_sched_wqueue_stop(&ring->sched);
|
||||
/* Get the last emitted fence sequence */
|
||||
wait_seq = atomic_read(&ring->fence_drv.last_seq);
|
||||
if (wait_seq)
|
||||
continue;
|
||||
|
||||
/* if Jobs are still pending after timeout,
|
||||
* We'll handle them in the bottom helper
|
||||
*/
|
||||
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v4_0_3_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
|
||||
ring = &adev->jpeg.inst[inst].ring_dec[i];
|
||||
/* Force completion of any remaining jobs */
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
|
||||
if (ring->use_doorbell)
|
||||
WREG32_SOC15_OFFSET(
|
||||
VCN, GET_INST(VCN, inst),
|
||||
regVCN_JPEG_DB_CTRL,
|
||||
(ring->pipe ? (ring->pipe - 0x15) : 0),
|
||||
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_JPEG_DB_CTRL__EN_MASK);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
drm_sched_wqueue_start(&ring->sched);
|
||||
|
||||
DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
|
||||
i, inst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
|
||||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
|
|
@ -1604,7 +1699,19 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
|
|||
int vcn_inst;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
|
||||
bool pg_state = false;
|
||||
|
||||
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
|
||||
mutex_lock(&vinst->engine_reset_mutex);
|
||||
mutex_lock(&adev->jpeg.jpeg_pg_lock);
|
||||
/* Ensure JPEG is powered on during reset if currently gated */
|
||||
if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
pg_state = true;
|
||||
}
|
||||
|
||||
vcn_v4_0_3_reset_jpeg_pre_helper(adev, ring->me);
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
|
||||
vcn_inst = GET_INST(VCN, ring->me);
|
||||
|
|
@ -1612,7 +1719,12 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
|
|||
|
||||
if (r) {
|
||||
DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
|
||||
return r;
|
||||
/* Restore JPEG power gating state if it was originally gated */
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* This flag is not set for VF, assumed to be disabled always */
|
||||
|
|
@ -1621,7 +1733,25 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
|
|||
vcn_v4_0_3_hw_init_inst(vinst);
|
||||
vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
|
||||
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
if (r) {
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
r = vcn_v4_0_3_reset_jpeg_post_helper(adev, ring->me);
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&vinst->engine_reset_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
|
||||
|
|
|
|||
|
|
@ -1301,6 +1301,59 @@ static void vcn_v5_0_1_unified_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
}
|
||||
}
|
||||
|
||||
static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
uint32_t wait_seq = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
|
||||
ring = &adev->jpeg.inst[inst].ring_dec[i];
|
||||
|
||||
drm_sched_wqueue_stop(&ring->sched);
|
||||
wait_seq = atomic_read(&ring->fence_drv.last_seq);
|
||||
if (wait_seq)
|
||||
continue;
|
||||
|
||||
/* if Jobs are still pending after timeout,
|
||||
* We'll handle them in the bottom helper
|
||||
*/
|
||||
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v5_0_1_reset_jpeg_post_helper(struct amdgpu_device *adev, int inst)
|
||||
{
|
||||
struct amdgpu_ring *ring;
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < adev->jpeg.num_jpeg_rings; ++i) {
|
||||
ring = &adev->jpeg.inst[inst].ring_dec[i];
|
||||
/* Force completion of any remaining jobs */
|
||||
amdgpu_fence_driver_force_completion(ring);
|
||||
|
||||
if (ring->use_doorbell)
|
||||
WREG32_SOC15_OFFSET(
|
||||
VCN, GET_INST(VCN, inst),
|
||||
regVCN_JPEG_DB_CTRL,
|
||||
(ring->pipe ? (ring->pipe - 0x15) : 0),
|
||||
ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
|
||||
VCN_JPEG_DB_CTRL__EN_MASK);
|
||||
|
||||
r = amdgpu_ring_test_helper(ring);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
drm_sched_wqueue_start(&ring->sched);
|
||||
|
||||
DRM_DEV_DEBUG(adev->dev, "JPEG ring %d (inst %d) restored and sched restarted\n",
|
||||
i, inst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
|
||||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
|
|
@ -1309,6 +1362,18 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
|
|||
int vcn_inst;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
|
||||
bool pg_state = false;
|
||||
|
||||
/* take the vcn reset mutex here because resetting VCN will reset jpeg as well */
|
||||
mutex_lock(&vinst->engine_reset_mutex);
|
||||
vcn_v5_0_1_reset_jpeg_pre_helper(adev, ring->me);
|
||||
mutex_lock(&adev->jpeg.jpeg_pg_lock);
|
||||
/* Ensure JPEG is powered on during reset if currently gated */
|
||||
if (adev->jpeg.cur_state == AMD_PG_STATE_GATE) {
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
pg_state = true;
|
||||
}
|
||||
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
|
||||
|
|
@ -1317,13 +1382,37 @@ static int vcn_v5_0_1_ring_reset(struct amdgpu_ring *ring,
|
|||
|
||||
if (r) {
|
||||
DRM_DEV_ERROR(adev->dev, "VCN reset fail : %d\n", r);
|
||||
return r;
|
||||
/* Restore JPEG power gating state if it was originally gated */
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
vcn_v5_0_1_hw_init_inst(adev, ring->me);
|
||||
vcn_v5_0_1_start_dpg_mode(vinst, vinst->indirect_sram);
|
||||
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
r = amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
if (r) {
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (pg_state)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
|
||||
r = vcn_v5_0_1_reset_jpeg_post_helper(adev, ring->me);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&vinst->engine_reset_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -35,6 +35,8 @@
|
|||
#define HAVE_BANKED_VGPRS (ASIC_FAMILY == CHIP_GC_12_0_3)
|
||||
#define NUM_NAMED_BARRIERS (ASIC_FAMILY == CHIP_GC_12_0_3 ? 0x10 : 0)
|
||||
#define HAVE_CLUSTER_BARRIER (ASIC_FAMILY == CHIP_GC_12_0_3)
|
||||
#define CLUSTER_BARRIER_SERIALIZE_WORKAROUND (ASIC_FAMILY == CHIP_GC_12_0_3)
|
||||
#define RELAXED_SCHEDULING_IN_TRAP (ASIC_FAMILY == CHIP_GFX12)
|
||||
|
||||
#define SINGLE_STEP_MISSED_WORKAROUND 1 //workaround for lost TRAP_AFTER_INST exception when SAVECTX raised
|
||||
#define HAVE_VALU_SGPR_HAZARD (ASIC_FAMILY == CHIP_GFX12)
|
||||
|
|
@ -104,10 +106,17 @@ var SQ_WAVE_SCHED_MODE_DEP_MODE_SHIFT = 0
|
|||
var SQ_WAVE_SCHED_MODE_DEP_MODE_SIZE = 2
|
||||
|
||||
var BARRIER_STATE_SIGNAL_OFFSET = 16
|
||||
var BARRIER_STATE_SIGNAL_SIZE = 7
|
||||
var BARRIER_STATE_MEMBER_OFFSET = 4
|
||||
var BARRIER_STATE_MEMBER_SIZE = 7
|
||||
var BARRIER_STATE_VALID_OFFSET = 0
|
||||
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
var TTMP11_SCHED_MODE_SHIFT = 26
|
||||
var TTMP11_SCHED_MODE_SIZE = 2
|
||||
var TTMP11_SCHED_MODE_MASK = 0xC000000
|
||||
#endif
|
||||
|
||||
var NAMED_BARRIERS_SR_OFFSET_FROM_HWREG = 0x80
|
||||
var S_BARRIER_INIT_MEMBERCNT_MASK = 0x7F0000
|
||||
var S_BARRIER_INIT_MEMBERCNT_SHIFT = 0x10
|
||||
|
|
@ -220,18 +229,22 @@ L_JUMP_TO_RESTORE:
|
|||
s_branch L_RESTORE
|
||||
|
||||
L_SKIP_RESTORE:
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
// Assume most relaxed scheduling mode is set. Save and revert to normal mode.
|
||||
s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_SCHED_MODE)
|
||||
s_wait_alu 0
|
||||
s_setreg_imm32_b32 hwreg(HW_REG_WAVE_SCHED_MODE, \
|
||||
SQ_WAVE_SCHED_MODE_DEP_MODE_SHIFT, SQ_WAVE_SCHED_MODE_DEP_MODE_SIZE), 0
|
||||
#endif
|
||||
|
||||
s_getreg_b32 s_save_state_priv, hwreg(HW_REG_WAVE_STATE_PRIV) //save STATUS since we will change SCC
|
||||
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
// Save SCHED_MODE[1:0] into ttmp11[27:26].
|
||||
s_andn2_b32 ttmp11, ttmp11, TTMP11_SCHED_MODE_MASK
|
||||
s_lshl_b32 ttmp2, ttmp2, TTMP11_SCHED_MODE_SHIFT
|
||||
s_or_b32 ttmp11, ttmp11, ttmp2
|
||||
#endif
|
||||
|
||||
// Clear SPI_PRIO: do not save with elevated priority.
|
||||
// Clear ECC_ERR: prevents SQC store and triggers FATAL_HALT if setreg'd.
|
||||
|
|
@ -313,7 +326,7 @@ L_FETCH_2ND_TRAP:
|
|||
s_cbranch_scc0 L_NO_SIGN_EXTEND_TMA
|
||||
s_or_b32 ttmp15, ttmp15, ~ADDRESS_HI32_MASK
|
||||
L_NO_SIGN_EXTEND_TMA:
|
||||
#if ASIC_FAMILY == CHIP_GFX12
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
// Move SCHED_MODE[1:0] from ttmp11 to unused bits in ttmp1[27:26] (return PC_HI).
|
||||
// The second-level trap will restore from ttmp1 for backwards compatibility.
|
||||
s_and_b32 ttmp2, ttmp11, TTMP11_SCHED_MODE_MASK
|
||||
|
|
@ -379,8 +392,10 @@ L_EXIT_TRAP:
|
|||
// Only restore fields which the trap handler changes.
|
||||
s_lshr_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_SCC_SHIFT
|
||||
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
// Assume relaxed scheduling mode after this point.
|
||||
restore_sched_mode(ttmp2)
|
||||
#endif
|
||||
|
||||
s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV, SQ_WAVE_STATE_PRIV_SCC_SHIFT, \
|
||||
SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT - SQ_WAVE_STATE_PRIV_SCC_SHIFT + 1), s_save_state_priv
|
||||
|
|
@ -519,9 +534,11 @@ L_SAVE_HWREG:
|
|||
v_mov_b32 v2, 0x0 //Set of SGPRs for TCP store
|
||||
s_mov_b32 m0, 0x0 //Next lane of v2 to write to
|
||||
|
||||
write_hwreg_to_v2(s_save_m0)
|
||||
|
||||
// Ensure no further changes to barrier or LDS state.
|
||||
// STATE_PRIV.*BARRIER_COMPLETE may change up to this point.
|
||||
wait_trap_barriers(s_save_tmp)
|
||||
wait_trap_barriers(s_save_tmp, s_save_m0, 1)
|
||||
|
||||
// Re-read final state of *BARRIER_COMPLETE fields for save.
|
||||
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATE_PRIV)
|
||||
|
|
@ -529,9 +546,8 @@ L_SAVE_HWREG:
|
|||
s_andn2_b32 s_save_state_priv, s_save_state_priv, SQ_WAVE_STATE_PRIV_ALL_BARRIER_COMPLETE_MASK
|
||||
s_or_b32 s_save_state_priv, s_save_state_priv, s_save_tmp
|
||||
|
||||
write_hwreg_to_v2(s_save_m0)
|
||||
write_hwreg_to_v2(s_save_pc_lo)
|
||||
s_andn2_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK
|
||||
s_and_b32 s_save_tmp, s_save_pc_hi, ADDRESS_HI32_MASK
|
||||
write_hwreg_to_v2(s_save_tmp)
|
||||
write_hwreg_to_v2(s_save_exec_lo)
|
||||
#if WAVE32_ONLY
|
||||
|
|
@ -587,8 +603,18 @@ L_SAVE_HWREG:
|
|||
write_hwreg_to_v2(s_save_tmp)
|
||||
#endif
|
||||
|
||||
#if ASIC_FAMILY >= CHIP_GC_12_0_3
|
||||
s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_SCHED_MODE)
|
||||
write_hwreg_to_v2(s_save_tmp)
|
||||
#endif
|
||||
|
||||
#if ! SAVE_TTMPS_IN_SGPR_BLOCK
|
||||
// Write HWREGs with 16 VGPR lanes. TTMPs occupy space after this.
|
||||
s_mov_b32 exec_lo, 0xFFFF
|
||||
#else
|
||||
// All 128 bytes are available for HWREGs.
|
||||
s_mov_b32 exec_lo, 0xFFFFFFFF
|
||||
#endif
|
||||
s_mov_b32 exec_hi, 0x0
|
||||
s_add_u32 s_save_addr_lo, s_save_base_addr_lo, s_save_mem_offset
|
||||
s_addc_u32 s_save_addr_hi, s_save_base_addr_hi, 0x0
|
||||
|
|
@ -1151,6 +1177,12 @@ L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL:
|
|||
L_SKIP_CLUSTER_BARRIER_RESTORE:
|
||||
#endif
|
||||
|
||||
#if ASIC_FAMILY >= CHIP_GC_12_0_3
|
||||
s_load_b32 s_restore_tmp, [s_restore_addr_lo, s_restore_addr_hi], null scope:SCOPE_SYS offset:0x40
|
||||
s_wait_kmcnt 0
|
||||
s_setreg_b32 hwreg(HW_REG_WAVE_SCHED_MODE), s_restore_tmp
|
||||
#endif
|
||||
|
||||
s_mov_b32 m0, s_restore_m0
|
||||
s_mov_b32 exec_lo, s_restore_exec_lo
|
||||
s_mov_b32 exec_hi, s_restore_exec_hi
|
||||
|
|
@ -1190,14 +1222,16 @@ L_SKIP_CLUSTER_BARRIER_RESTORE:
|
|||
s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32
|
||||
s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32
|
||||
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
// Assume relaxed scheduling mode after this point.
|
||||
restore_sched_mode(s_restore_tmp)
|
||||
#endif
|
||||
|
||||
s_setreg_b32 hwreg(HW_REG_WAVE_STATE_PRIV), s_restore_state_priv // SCC is included, which is changed by previous salu
|
||||
|
||||
// Make barrier and LDS state visible to all waves in the group/cluster.
|
||||
// STATE_PRIV.*BARRIER_COMPLETE may change after this point.
|
||||
wait_trap_barriers(s_restore_tmp)
|
||||
wait_trap_barriers(s_restore_tmp, 0, 0)
|
||||
|
||||
#if HAVE_CLUSTER_BARRIER
|
||||
// SCC is changed by wait_trap_barriers, restore it separately.
|
||||
|
|
@ -1210,7 +1244,7 @@ L_SKIP_CLUSTER_BARRIER_RESTORE:
|
|||
L_END_PGM:
|
||||
// Make sure that no wave of the group/cluster can exit the trap handler
|
||||
// before the group/cluster barrier state is saved.
|
||||
wait_trap_barriers(s_restore_tmp)
|
||||
wait_trap_barriers(s_restore_tmp, 0, 0)
|
||||
|
||||
s_endpgm_saved
|
||||
end
|
||||
|
|
@ -1300,11 +1334,11 @@ function restore_xnack_state_priv(s_tmp)
|
|||
end
|
||||
#endif
|
||||
|
||||
function wait_trap_barriers(s_tmp)
|
||||
function wait_trap_barriers(s_tmp1, s_tmp2, serialize_wa)
|
||||
#if HAVE_CLUSTER_BARRIER
|
||||
// If not in a WG then wave cannot use s_barrier_signal_isfirst.
|
||||
s_getreg_b32 s_tmp, hwreg(HW_REG_WAVE_STATUS)
|
||||
s_bitcmp0_b32 s_tmp, SQ_WAVE_STATUS_IN_WG_SHIFT
|
||||
s_getreg_b32 s_tmp1, hwreg(HW_REG_WAVE_STATUS)
|
||||
s_bitcmp0_b32 s_tmp1, SQ_WAVE_STATUS_IN_WG_SHIFT
|
||||
s_cbranch_scc1 L_TRAP_CLUSTER_BARRIER_SIGNAL
|
||||
|
||||
s_barrier_signal_isfirst -2
|
||||
|
|
@ -1318,15 +1352,37 @@ L_TRAP_CLUSTER_BARRIER_SIGNAL:
|
|||
|
||||
L_SKIP_TRAP_CLUSTER_BARRIER_SIGNAL:
|
||||
s_barrier_wait -4
|
||||
|
||||
#if CLUSTER_BARRIER_SERIALIZE_WORKAROUND
|
||||
if serialize_wa
|
||||
// Trap cluster barrier may complete with a user cluster barrier in-flight.
|
||||
// This is indicated if user cluster member count and signal count are equal.
|
||||
L_WAIT_USER_CLUSTER_BARRIER_COMPLETE:
|
||||
s_sendmsg_rtn_b32 s_tmp1, sendmsg(MSG_RTN_GET_CLUSTER_BARRIER_STATE)
|
||||
s_wait_kmcnt 0
|
||||
s_bitcmp0_b32 s_tmp1, BARRIER_STATE_VALID_OFFSET
|
||||
s_cbranch_scc1 L_NOT_IN_CLUSTER
|
||||
|
||||
s_bfe_u32 s_tmp2, s_tmp1, (BARRIER_STATE_MEMBER_OFFSET | (BARRIER_STATE_MEMBER_SIZE << 0x10))
|
||||
s_bfe_u32 s_tmp1, s_tmp1, (BARRIER_STATE_SIGNAL_OFFSET | (BARRIER_STATE_SIGNAL_SIZE << 0x10))
|
||||
s_cmp_eq_u32 s_tmp1, s_tmp2
|
||||
s_cbranch_scc1 L_WAIT_USER_CLUSTER_BARRIER_COMPLETE
|
||||
end
|
||||
L_NOT_IN_CLUSTER:
|
||||
#endif
|
||||
|
||||
#else
|
||||
s_barrier_signal -2
|
||||
s_barrier_wait -2
|
||||
#endif
|
||||
end
|
||||
|
||||
#if RELAXED_SCHEDULING_IN_TRAP
|
||||
function restore_sched_mode(s_tmp)
|
||||
s_bfe_u32 s_tmp, ttmp11, (TTMP11_SCHED_MODE_SHIFT | (TTMP11_SCHED_MODE_SIZE << 0x10))
|
||||
s_setreg_b32 hwreg(HW_REG_WAVE_SCHED_MODE), s_tmp
|
||||
end
|
||||
#endif
|
||||
|
||||
function restore_barrier_signal_count(barrier_id)
|
||||
// extract the saved signal count from s_restore_tmp
|
||||
|
|
@ -1354,8 +1410,8 @@ function fixup_vgpr_bank_selection
|
|||
// ttmp[0:1]: {7b'0} PC[56:0]
|
||||
// ttmp2, 3, 10, 13, 14, 15: free
|
||||
s_load_b64 [ttmp14, ttmp15], [ttmp0, ttmp1], 0 scope:SCOPE_CU // Load the 2 instruction DW we are returning to
|
||||
s_wait_kmcnt 0
|
||||
s_load_b64 [ttmp2, ttmp3], [ttmp0, ttmp1], 8 scope:SCOPE_CU // Load the next 2 instruction DW, just in case
|
||||
s_wait_kmcnt 1
|
||||
s_and_b32 ttmp10, ttmp14, 0x80000000 // Check bit 31 in the first DWORD
|
||||
// SCC set if ttmp10 is != 0, i.e. if bit 31 == 1
|
||||
s_cbranch_scc1 L_FIXUP_NOT_VOP12C // If bit 31 is 1, we are not VOP1, VOP2, or VOP3C
|
||||
|
|
|
|||
|
|
@ -120,8 +120,7 @@ static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
|
|||
&& dev->kfd->mec2_fw_version < 0x1b6) ||
|
||||
(KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1)
|
||||
&& dev->kfd->mec2_fw_version < 0x30) ||
|
||||
(KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
|
||||
KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0)))
|
||||
kfd_dbg_has_cwsr_workaround(dev))
|
||||
return false;
|
||||
|
||||
/* Assume debugging and cooperative launch supported otherwise. */
|
||||
|
|
|
|||
|
|
@ -109,6 +109,17 @@ static void set_priority(struct v9_mqd *m, struct queue_properties *q)
|
|||
m->cp_hqd_queue_priority = q->priority;
|
||||
}
|
||||
|
||||
static bool mqd_on_vram(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(9, 4, 3):
|
||||
case IP_VERSION(9, 5, 0):
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
|
|
@ -139,7 +150,8 @@ static struct kfd_mem_obj *allocate_mqd(struct kfd_node *node,
|
|||
(ALIGN(q->ctl_stack_size, PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
|
||||
NUM_XCC(node->xcc_mask),
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
mqd_on_vram(node->adev) ? AMDGPU_GEM_DOMAIN_VRAM :
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
&(mqd_mem_obj->mem),
|
||||
&(mqd_mem_obj->gpu_addr),
|
||||
(void *)&(mqd_mem_obj->cpu_ptr), true);
|
||||
|
|
@ -739,6 +751,9 @@ static void init_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
|
|||
*gart_addr = xcc_gart_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mqd_on_vram(mm->dev->adev))
|
||||
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
|
||||
}
|
||||
|
||||
static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
|
||||
|
|
@ -775,6 +790,9 @@ static void update_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
|
|||
m->pm4_target_xcc_in_xcp = q->pm4_target_xcc;
|
||||
}
|
||||
}
|
||||
|
||||
if (mqd_on_vram(mm->dev->adev))
|
||||
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
|
||||
}
|
||||
|
||||
static void restore_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
|
||||
|
|
@ -813,6 +831,9 @@ static void restore_mqd_v9_4_3(struct mqd_manager *mm, void **mqd,
|
|||
(uint8_t *)ctl_stack_src + xcc * mqd_ctl_stack_size,
|
||||
mqd_ctl_stack_size);
|
||||
}
|
||||
|
||||
if (mqd_on_vram(mm->dev->adev))
|
||||
amdgpu_device_flush_hdp(mm->dev->adev, NULL);
|
||||
}
|
||||
static int destroy_mqd_v9_4_3(struct mqd_manager *mm, void *mqd,
|
||||
enum kfd_preempt_type type, unsigned int timeout,
|
||||
|
|
|
|||
|
|
@ -1372,7 +1372,6 @@ static int
|
|||
svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
|
||||
unsigned long last, uint32_t trigger)
|
||||
{
|
||||
DECLARE_BITMAP(bitmap, MAX_GPU_INSTANCE);
|
||||
struct kfd_process_device *pdd;
|
||||
struct dma_fence *fence = NULL;
|
||||
struct kfd_process *p;
|
||||
|
|
@ -1390,11 +1389,9 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
|
|||
prange->mapped_to_gpu = false;
|
||||
}
|
||||
|
||||
bitmap_or(bitmap, prange->bitmap_access, prange->bitmap_aip,
|
||||
MAX_GPU_INSTANCE);
|
||||
p = container_of(prange->svms, struct kfd_process, svms);
|
||||
|
||||
for_each_set_bit(gpuidx, bitmap, MAX_GPU_INSTANCE) {
|
||||
for_each_or_bit(gpuidx, prange->bitmap_access, prange->bitmap_aip, MAX_GPU_INSTANCE) {
|
||||
pr_debug("unmap from gpu idx 0x%x\n", gpuidx);
|
||||
pdd = kfd_process_device_from_gpuidx(p, gpuidx);
|
||||
if (!pdd) {
|
||||
|
|
|
|||
|
|
@ -7768,10 +7768,12 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
|
|||
drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
|
||||
|
||||
/* Cancel and flush any pending HDMI HPD debounce work */
|
||||
cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
|
||||
if (aconnector->hdmi_prev_sink) {
|
||||
dc_sink_release(aconnector->hdmi_prev_sink);
|
||||
aconnector->hdmi_prev_sink = NULL;
|
||||
if (aconnector->hdmi_hpd_debounce_delay_ms) {
|
||||
cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work);
|
||||
if (aconnector->hdmi_prev_sink) {
|
||||
dc_sink_release(aconnector->hdmi_prev_sink);
|
||||
aconnector->hdmi_prev_sink = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (aconnector->bl_idx != -1) {
|
||||
|
|
@ -13144,9 +13146,24 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
|
|||
|
||||
if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
|
||||
amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
|
||||
u8 panel_type;
|
||||
vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
|
||||
vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
|
||||
drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode);
|
||||
panel_type = (amd_vsdb->color_space_eotf_support & AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT;
|
||||
switch (panel_type) {
|
||||
case AMD_VSDB_PANEL_TYPE_OLED:
|
||||
aconnector->dc_link->panel_type = PANEL_TYPE_OLED;
|
||||
break;
|
||||
case AMD_VSDB_PANEL_TYPE_MINILED:
|
||||
aconnector->dc_link->panel_type = PANEL_TYPE_MINILED;
|
||||
break;
|
||||
default:
|
||||
aconnector->dc_link->panel_type = PANEL_TYPE_NONE;
|
||||
break;
|
||||
}
|
||||
drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n",
|
||||
aconnector->dc_link->panel_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,17 @@
|
|||
|
||||
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
|
||||
#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
|
||||
#define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0
|
||||
#define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6
|
||||
#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
|
||||
|
||||
enum amd_vsdb_panel_type {
|
||||
AMD_VSDB_PANEL_TYPE_DEFAULT = 0,
|
||||
AMD_VSDB_PANEL_TYPE_MINILED,
|
||||
AMD_VSDB_PANEL_TYPE_OLED,
|
||||
AMD_VSDB_PANEL_TYPE_RESERVED,
|
||||
};
|
||||
|
||||
#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
|
||||
|
||||
/*
|
||||
|
|
@ -92,6 +101,8 @@ struct amd_vsdb_block {
|
|||
unsigned char ieee_id[3];
|
||||
unsigned char version;
|
||||
unsigned char feature_caps;
|
||||
unsigned char reserved[3];
|
||||
unsigned char color_space_eotf_support;
|
||||
};
|
||||
|
||||
struct common_irq_params {
|
||||
|
|
|
|||
|
|
@ -248,8 +248,6 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
|
|||
struct vblank_control_work *vblank_work =
|
||||
container_of(work, struct vblank_control_work, work);
|
||||
struct amdgpu_display_manager *dm = vblank_work->dm;
|
||||
struct amdgpu_device *adev = drm_to_adev(dm->ddev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&dm->dc_lock);
|
||||
|
||||
|
|
@ -279,16 +277,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
|
|||
|
||||
if (dm->active_vblank_irq_count == 0) {
|
||||
dc_post_update_surfaces_to_stream(dm->dc);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, true);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to set default power profile mode\n");
|
||||
|
||||
dc_allow_idle_optimizations(dm->dc, true);
|
||||
|
||||
r = amdgpu_dpm_pause_power_profile(adev, false);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "failed to restore the power profile mode\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&dm->dc_lock);
|
||||
|
|
|
|||
|
|
@ -2709,6 +2709,65 @@ static int ips_status_show(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPS residency information from DMUB service. Read only.
|
||||
*
|
||||
* For time-window (segment) measurement:
|
||||
* 1) echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
|
||||
* 2) sleep <seconds>
|
||||
* 3) echo 0 > /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency_cntl
|
||||
* 4) cat /sys/kernel/debug/dri/0/amdgpu_dm_ips_residency
|
||||
*/
|
||||
static int ips_residency_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct amdgpu_device *adev = m->private;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
uint8_t panel_inst = 0;
|
||||
enum ips_residency_mode mode;
|
||||
struct dmub_ips_residency_info info;
|
||||
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
|
||||
mode = IPS_RESIDENCY__IPS1_RCG;
|
||||
if (!dc_dmub_srv_ips_query_residency_info(dc->ctx, panel_inst, &info, mode)) {
|
||||
seq_printf(m, "ISP query failed\n");
|
||||
} else {
|
||||
unsigned int pct, frac;
|
||||
pct = info.residency_millipercent / 1000;
|
||||
frac = info.residency_millipercent % 1000;
|
||||
|
||||
seq_printf(m, "IPS residency: %u.%03u%% \n", pct, frac);
|
||||
seq_printf(m, " entry_counter: %u\n", info.entry_counter);
|
||||
seq_printf(m, " total_time_us: %llu\n",
|
||||
(unsigned long long)info.total_time_us);
|
||||
seq_printf(m, " total_inactive_time_us: %llu\n",
|
||||
(unsigned long long)info.total_inactive_time_us);
|
||||
}
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ips_residency_cntl_get(void *data, u64 *val)
|
||||
{
|
||||
*val = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ips_residency_cntl_set(void *data, u64 val)
|
||||
{
|
||||
struct amdgpu_device *adev = data;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
uint8_t panel_inst = 0;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&adev->dm.dc_lock);
|
||||
if (!dc_dmub_srv_ips_residency_cntl(dc->ctx, panel_inst, !!val))
|
||||
ret = -EIO;
|
||||
mutex_unlock(&adev->dm.dc_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Backlight at this moment. Read only.
|
||||
* As written to display, taking ABM and backlight lut into account.
|
||||
|
|
@ -3370,9 +3429,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,
|
|||
disallow_edp_enter_psr_get,
|
||||
disallow_edp_enter_psr_set, "%llu\n");
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get,
|
||||
ips_residency_cntl_set, "%llu\n");
|
||||
DEFINE_SHOW_ATTRIBUTE(current_backlight);
|
||||
DEFINE_SHOW_ATTRIBUTE(target_backlight);
|
||||
DEFINE_SHOW_ATTRIBUTE(ips_status);
|
||||
DEFINE_SHOW_ATTRIBUTE(ips_residency);
|
||||
|
||||
static const struct {
|
||||
char *name;
|
||||
|
|
@ -4271,7 +4333,14 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
|
|||
debugfs_create_file_unsafe("amdgpu_dm_disable_hpd", 0644, root, adev,
|
||||
&disable_hpd_ops);
|
||||
|
||||
if (adev->dm.dc->caps.ips_support)
|
||||
if (adev->dm.dc->caps.ips_support) {
|
||||
debugfs_create_file_unsafe("amdgpu_dm_ips_status", 0644, root, adev,
|
||||
&ips_status_fops);
|
||||
|
||||
debugfs_create_file_unsafe("amdgpu_dm_ips_residency_cntl", 0644, root, adev,
|
||||
&ips_residency_cntl_fops);
|
||||
|
||||
debugfs_create_file_unsafe("amdgpu_dm_ips_residency", 0644, root, adev,
|
||||
&ips_residency_fops);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,12 @@ void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
|
|||
/* TODO: something */
|
||||
}
|
||||
|
||||
void dm_helpers_dmu_timeout(struct dc_context *ctx)
|
||||
{
|
||||
// TODO:
|
||||
//amdgpu_device_gpu_recover(dc_context->driver-context, NULL);
|
||||
}
|
||||
|
||||
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us)
|
||||
{
|
||||
// TODO:
|
||||
|
|
|
|||
|
|
@ -915,13 +915,19 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
|||
struct amdgpu_dm_connector *amdgpu_dm_connector;
|
||||
const struct dc_link *dc_link;
|
||||
|
||||
use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
continue;
|
||||
|
||||
amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
|
||||
|
||||
/*
|
||||
* Analog connectors may be hot-plugged unlike other connector
|
||||
* types that don't support HPD. Only poll analog connectors.
|
||||
*/
|
||||
use_polling |=
|
||||
amdgpu_dm_connector->dc_link &&
|
||||
dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
|
||||
|
||||
dc_link = amdgpu_dm_connector->dc_link;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
|
|||
#undef DC_LOGGER
|
||||
#define DC_LOGGER \
|
||||
clk_mgr->base.base.ctx->logger
|
||||
|
||||
#define regCLK1_CLK_PLL_REQ 0x0237
|
||||
#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
|
||||
|
||||
|
|
@ -88,70 +87,8 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0,
|
|||
#define CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
|
||||
#define CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
|
||||
|
||||
#define regCLK1_CLK0_DFS_CNTL 0x0269
|
||||
#define regCLK1_CLK0_DFS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK1_DFS_CNTL 0x026c
|
||||
#define regCLK1_CLK1_DFS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK2_DFS_CNTL 0x026f
|
||||
#define regCLK1_CLK2_DFS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK3_DFS_CNTL 0x0272
|
||||
#define regCLK1_CLK3_DFS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK4_DFS_CNTL 0x0275
|
||||
#define regCLK1_CLK4_DFS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK5_DFS_CNTL 0x0278
|
||||
#define regCLK1_CLK5_DFS_CNTL_BASE_IDX 0
|
||||
|
||||
#define regCLK1_CLK0_CURRENT_CNT 0x02fb
|
||||
#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK1_CURRENT_CNT 0x02fc
|
||||
#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK2_CURRENT_CNT 0x02fd
|
||||
#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK3_CURRENT_CNT 0x02fe
|
||||
#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK4_CURRENT_CNT 0x02ff
|
||||
#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK5_CURRENT_CNT 0x0300
|
||||
#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
|
||||
|
||||
#define regCLK1_CLK0_BYPASS_CNTL 0x028a
|
||||
#define regCLK1_CLK0_BYPASS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK1_BYPASS_CNTL 0x0293
|
||||
#define regCLK1_CLK1_BYPASS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK2_BYPASS_CNTL 0x029c
|
||||
#define regCLK1_CLK2_BYPASS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK3_BYPASS_CNTL 0x02a5
|
||||
#define regCLK1_CLK3_BYPASS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK4_BYPASS_CNTL 0x02ae
|
||||
#define regCLK1_CLK4_BYPASS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK5_BYPASS_CNTL 0x02b7
|
||||
#define regCLK1_CLK5_BYPASS_CNTL_BASE_IDX 0
|
||||
|
||||
#define regCLK1_CLK0_DS_CNTL 0x0283
|
||||
#define regCLK1_CLK0_DS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK1_DS_CNTL 0x028c
|
||||
#define regCLK1_CLK1_DS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK2_DS_CNTL 0x0295
|
||||
#define regCLK1_CLK2_DS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK3_DS_CNTL 0x029e
|
||||
#define regCLK1_CLK3_DS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK4_DS_CNTL 0x02a7
|
||||
#define regCLK1_CLK4_DS_CNTL_BASE_IDX 0
|
||||
#define regCLK1_CLK5_DS_CNTL 0x02b0
|
||||
#define regCLK1_CLK5_DS_CNTL_BASE_IDX 0
|
||||
|
||||
#define regCLK1_CLK0_ALLOW_DS 0x0284
|
||||
#define regCLK1_CLK0_ALLOW_DS_BASE_IDX 0
|
||||
#define regCLK1_CLK1_ALLOW_DS 0x028d
|
||||
#define regCLK1_CLK1_ALLOW_DS_BASE_IDX 0
|
||||
#define regCLK1_CLK2_ALLOW_DS 0x0296
|
||||
#define regCLK1_CLK2_ALLOW_DS_BASE_IDX 0
|
||||
#define regCLK1_CLK3_ALLOW_DS 0x029f
|
||||
#define regCLK1_CLK3_ALLOW_DS_BASE_IDX 0
|
||||
#define regCLK1_CLK4_ALLOW_DS 0x02a8
|
||||
#define regCLK1_CLK4_ALLOW_DS_BASE_IDX 0
|
||||
#define regCLK1_CLK5_ALLOW_DS 0x02b1
|
||||
#define regCLK1_CLK5_ALLOW_DS_BASE_IDX 0
|
||||
|
||||
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT 0x0
|
||||
#define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT 0x10
|
||||
|
|
@ -248,8 +185,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
|
|||
{
|
||||
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
|
||||
uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
|
||||
struct clk_mgr_dcn314 *clk_mgr_dcn314 = TO_CLK_MGR_DCN314(clk_mgr_int);
|
||||
struct clk_log_info log_info = {0};
|
||||
|
||||
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
|
||||
// Assumption is that boot state always supports pstate
|
||||
|
|
@ -265,9 +200,6 @@ void dcn314_init_clocks(struct clk_mgr *clk_mgr)
|
|||
dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr->dprefclk_khz);
|
||||
else
|
||||
clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz;
|
||||
|
||||
dcn314_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn314->base.base, &log_info);
|
||||
clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
|
||||
}
|
||||
|
||||
void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
||||
|
|
@ -278,7 +210,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
|
||||
struct dc *dc = clk_mgr_base->ctx->dc;
|
||||
int display_count;
|
||||
int display_count = 0;
|
||||
bool update_dppclk = false;
|
||||
bool update_dispclk = false;
|
||||
bool dpp_clock_lowered = false;
|
||||
|
|
@ -287,7 +219,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
return;
|
||||
|
||||
display_count = dcn314_get_active_display_cnt_wa(dc, context);
|
||||
|
||||
/*
|
||||
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
|
||||
* also if safe to lower is false, we just go in the higher state
|
||||
|
|
@ -363,7 +294,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
}
|
||||
|
||||
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
|
||||
(new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
|
||||
(new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
|
||||
int requested_dispclk_khz = new_clocks->dispclk_khz;
|
||||
|
||||
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
|
||||
|
|
@ -374,7 +305,6 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
|
||||
dcn314_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
|
||||
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
|
||||
|
||||
dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
|
||||
|
||||
update_dispclk = true;
|
||||
|
|
@ -462,65 +392,10 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void dcn314_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
|
||||
// read dtbclk
|
||||
internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
|
||||
internal->CLK1_CLK4_BYPASS_CNTL = REG_READ(CLK1_CLK4_BYPASS_CNTL);
|
||||
|
||||
// read dcfclk
|
||||
internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
|
||||
internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);
|
||||
|
||||
// read dcf deep sleep divider
|
||||
internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);
|
||||
internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);
|
||||
|
||||
// read dppclk
|
||||
internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
|
||||
internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);
|
||||
|
||||
// read dprefclk
|
||||
internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
|
||||
internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);
|
||||
|
||||
// read dispclk
|
||||
internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
|
||||
internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
|
||||
}
|
||||
|
||||
void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
static void dcn314_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 dcn35_clk_internal internal = {0};
|
||||
|
||||
dcn314_dump_clk_registers_internal(&internal, clk_mgr_base);
|
||||
|
||||
regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
|
||||
regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
|
||||
regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
|
||||
|
||||
regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dppclk_bypass > 4)
|
||||
regs_and_bypass->dppclk_bypass = 0;
|
||||
regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dcfclk_bypass > 4)
|
||||
regs_and_bypass->dcfclk_bypass = 0;
|
||||
regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dispclk_bypass > 4)
|
||||
regs_and_bypass->dispclk_bypass = 0;
|
||||
regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
|
||||
if (regs_and_bypass->dprefclk_bypass > 4)
|
||||
regs_and_bypass->dprefclk_bypass = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct clk_bw_params dcn314_bw_params = {
|
||||
|
|
|
|||
|
|
@ -65,9 +65,4 @@ void dcn314_clk_mgr_construct(struct dc_context *ctx,
|
|||
|
||||
void dcn314_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
|
||||
|
||||
|
||||
void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
|
||||
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info);
|
||||
|
||||
|
||||
#endif //__DCN314_CLK_MGR_H__
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include "dm_helpers.h"
|
||||
|
||||
#include "dc_dmub_srv.h"
|
||||
#include "reg_helper.h"
|
||||
|
||||
#include "logger_types.h"
|
||||
#undef DC_LOGGER
|
||||
#define DC_LOGGER \
|
||||
|
|
@ -48,43 +48,9 @@
|
|||
|
||||
#include "link_service.h"
|
||||
|
||||
#define MAX_INSTANCE 7
|
||||
#define MAX_SEGMENT 8
|
||||
|
||||
struct IP_BASE_INSTANCE {
|
||||
unsigned int segment[MAX_SEGMENT];
|
||||
};
|
||||
|
||||
struct IP_BASE {
|
||||
struct IP_BASE_INSTANCE instance[MAX_INSTANCE];
|
||||
};
|
||||
|
||||
static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0, 0, 0, 0 } },
|
||||
{ { 0x00016E00, 0x02401C00, 0, 0, 0, 0, 0, 0 } },
|
||||
{ { 0x00017000, 0x02402000, 0, 0, 0, 0, 0, 0 } },
|
||||
{ { 0x00017200, 0x02402400, 0, 0, 0, 0, 0, 0 } },
|
||||
{ { 0x0001B000, 0x0242D800, 0, 0, 0, 0, 0, 0 } },
|
||||
{ { 0x0001B200, 0x0242DC00, 0, 0, 0, 0, 0, 0 } } } };
|
||||
|
||||
#define regCLK1_CLK0_CURRENT_CNT 0x0314
|
||||
#define regCLK1_CLK0_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK1_CURRENT_CNT 0x0315
|
||||
#define regCLK1_CLK1_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK2_CURRENT_CNT 0x0316
|
||||
#define regCLK1_CLK2_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK3_CURRENT_CNT 0x0317
|
||||
#define regCLK1_CLK3_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK4_CURRENT_CNT 0x0318
|
||||
#define regCLK1_CLK4_CURRENT_CNT_BASE_IDX 0
|
||||
#define regCLK1_CLK5_CURRENT_CNT 0x0319
|
||||
#define regCLK1_CLK5_CURRENT_CNT_BASE_IDX 0
|
||||
|
||||
#define TO_CLK_MGR_DCN315(clk_mgr)\
|
||||
container_of(clk_mgr, struct clk_mgr_dcn315, base)
|
||||
|
||||
#define REG(reg_name) \
|
||||
(CLK_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
|
||||
|
||||
#define UNSUPPORTED_DCFCLK 10000000
|
||||
#define MIN_DPP_DISP_CLK 100000
|
||||
|
||||
|
|
@ -172,7 +138,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
if (dc->work_arounds.skip_clock_update)
|
||||
return;
|
||||
|
||||
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
|
||||
display_count = dcn315_get_active_display_cnt_wa(dc, context);
|
||||
/*
|
||||
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
|
||||
* also if safe to lower is false, we just go in the higher state
|
||||
|
|
@ -185,7 +151,6 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
}
|
||||
/* check that we're not already in lower */
|
||||
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
|
||||
display_count = dcn315_get_active_display_cnt_wa(dc, context);
|
||||
/* if we can go lower, go lower */
|
||||
if (display_count == 0) {
|
||||
union display_idle_optimization_u idle_info = { 0 };
|
||||
|
|
@ -279,38 +244,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
|
|||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
}
|
||||
|
||||
static void dcn315_dump_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
|
||||
|
||||
// read dtbclk
|
||||
internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
|
||||
|
||||
// read dcfclk
|
||||
internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
|
||||
|
||||
// read dppclk
|
||||
internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
|
||||
|
||||
// read dprefclk
|
||||
internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
|
||||
|
||||
// read dispclk
|
||||
internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
|
||||
}
|
||||
|
||||
static void dcn315_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 dcn35_clk_internal internal = {0};
|
||||
|
||||
dcn315_dump_clk_registers_internal(&internal, clk_mgr_base);
|
||||
|
||||
regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
|
||||
regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -657,32 +593,13 @@ static struct clk_mgr_funcs dcn315_funcs = {
|
|||
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
|
||||
.get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
|
||||
.update_clocks = dcn315_update_clocks,
|
||||
.init_clocks = dcn315_init_clocks,
|
||||
.init_clocks = dcn31_init_clocks,
|
||||
.enable_pme_wa = dcn315_enable_pme_wa,
|
||||
.are_clock_states_equal = dcn31_are_clock_states_equal,
|
||||
.notify_wm_ranges = dcn315_notify_wm_ranges
|
||||
};
|
||||
extern struct clk_mgr_funcs dcn3_fpga_funcs;
|
||||
|
||||
void dcn315_init_clocks(struct clk_mgr *clk_mgr)
|
||||
{
|
||||
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
|
||||
uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
|
||||
struct clk_mgr_dcn315 *clk_mgr_dcn315 = TO_CLK_MGR_DCN315(clk_mgr_int);
|
||||
struct clk_log_info log_info = {0};
|
||||
|
||||
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
|
||||
// Assumption is that boot state always supports pstate
|
||||
clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
|
||||
clk_mgr->clks.p_state_change_support = true;
|
||||
clk_mgr->clks.prev_p_state_change_support = true;
|
||||
clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
|
||||
clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
|
||||
|
||||
dcn315_dump_clk_registers(&clk_mgr->boot_snapshot, &clk_mgr_dcn315->base.base, &log_info);
|
||||
clk_mgr->clks.dispclk_khz = clk_mgr->boot_snapshot.dispclk * 1000;
|
||||
}
|
||||
|
||||
void dcn315_clk_mgr_construct(
|
||||
struct dc_context *ctx,
|
||||
struct clk_mgr_dcn315 *clk_mgr,
|
||||
|
|
@ -743,7 +660,6 @@ void dcn315_clk_mgr_construct(
|
|||
/* Saved clocks configured at boot for debug purposes */
|
||||
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
|
||||
&clk_mgr->base.base, &log_info);
|
||||
clk_mgr->base.base.clks.dispclk_khz = clk_mgr->base.base.boot_snapshot.dispclk * 1000;
|
||||
|
||||
clk_mgr->base.base.dprefclk_khz = 600000;
|
||||
clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ void dcn315_clk_mgr_construct(struct dc_context *ctx,
|
|||
struct pp_smu_funcs *pp_smu,
|
||||
struct dccg *dccg);
|
||||
|
||||
void dcn315_init_clocks(struct clk_mgr *clk_mgr);
|
||||
void dcn315_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
|
||||
|
||||
#endif //__DCN315_CLK_MGR_H__
|
||||
|
|
|
|||
|
|
@ -7143,22 +7143,24 @@ void dc_log_preos_dmcub_info(const struct dc *dc)
|
|||
bool dc_get_qos_info(struct dc *dc, struct dc_qos_info *info)
|
||||
{
|
||||
const struct dc_clocks *clk = &dc->current_state->bw_ctx.bw.dcn.clk;
|
||||
struct memory_qos qos;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
// Check if all measurement functions are available
|
||||
if (!dc->hwss.measure_peak_bw_mbps ||
|
||||
!dc->hwss.measure_avg_bw_mbps ||
|
||||
!dc->hwss.measure_max_latency_ns ||
|
||||
!dc->hwss.measure_avg_latency_ns) {
|
||||
// Check if measurement function is available
|
||||
if (!dc->hwss.measure_memory_qos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call measurement functions to get actual values
|
||||
info->actual_peak_bw_in_mbps = dc->hwss.measure_peak_bw_mbps(dc);
|
||||
info->actual_avg_bw_in_mbps = dc->hwss.measure_avg_bw_mbps(dc);
|
||||
info->actual_max_latency_in_ns = dc->hwss.measure_max_latency_ns(dc);
|
||||
info->actual_avg_latency_in_ns = dc->hwss.measure_avg_latency_ns(dc);
|
||||
// Call unified measurement function
|
||||
dc->hwss.measure_memory_qos(dc, &qos);
|
||||
|
||||
// Populate info from measured qos
|
||||
info->actual_peak_bw_in_mbps = qos.peak_bw_mbps;
|
||||
info->actual_avg_bw_in_mbps = qos.avg_bw_mbps;
|
||||
info->actual_min_latency_in_ns = qos.min_latency_ns;
|
||||
info->actual_max_latency_in_ns = qos.max_latency_ns;
|
||||
info->actual_avg_latency_in_ns = qos.avg_latency_ns;
|
||||
info->dcn_bandwidth_ub_in_mbps = (uint32_t)(clk->fclk_khz / 1000 * 64);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
|
|||
struct dcn_optc_reg_state;
|
||||
struct dcn_dccg_reg_state;
|
||||
|
||||
#define DC_VER "3.2.365"
|
||||
#define DC_VER "3.2.366"
|
||||
|
||||
/**
|
||||
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
|
||||
|
|
@ -962,6 +962,7 @@ struct dc_qos_info {
|
|||
uint32_t actual_avg_bw_in_mbps;
|
||||
uint32_t calculated_avg_bw_in_mbps;
|
||||
uint32_t actual_max_latency_in_ns;
|
||||
uint32_t actual_min_latency_in_ns;
|
||||
uint32_t qos_max_latency_ub_in_ns;
|
||||
uint32_t actual_avg_latency_in_ns;
|
||||
uint32_t qos_avg_latency_ub_in_ns;
|
||||
|
|
@ -1208,6 +1209,7 @@ struct dc_debug_options {
|
|||
uint32_t custom_psp_footer_size;
|
||||
bool disable_deferred_minimal_transitions;
|
||||
unsigned int num_fast_flips_to_steady_state_override;
|
||||
bool enable_dmu_recovery;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1733,6 +1735,7 @@ struct dc_scratch_space {
|
|||
bool link_powered_externally; // Used to bypass hardware sequencing delays when panel is powered down forcibly
|
||||
|
||||
struct dc_panel_config panel_config;
|
||||
enum dc_panel_type panel_type;
|
||||
struct phy_state phy_state;
|
||||
uint32_t phy_transition_bitmask;
|
||||
// BW ALLOCATON USB4 ONLY
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#define DC_LOGGER CTX->logger
|
||||
#define GPINT_RETRY_NUM 20
|
||||
|
||||
#define MAX_WAIT_US 100000
|
||||
|
||||
static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
|
||||
struct dmub_srv *dmub)
|
||||
{
|
||||
|
|
@ -48,6 +50,13 @@ static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
|
|||
dc_srv->ctx = dc->ctx;
|
||||
}
|
||||
|
||||
static void dc_dmub_srv_handle_failure(struct dc_dmub_srv *dc_dmub_srv)
|
||||
{
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
if (dc_dmub_srv->ctx->dc->debug.enable_dmu_recovery)
|
||||
dm_helpers_dmu_timeout(dc_dmub_srv->ctx);
|
||||
}
|
||||
|
||||
struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
|
||||
{
|
||||
struct dc_dmub_srv *dc_srv =
|
||||
|
|
@ -84,12 +93,12 @@ bool dc_dmub_srv_wait_for_pending(struct dc_dmub_srv *dc_dmub_srv)
|
|||
dmub = dc_dmub_srv->dmub;
|
||||
|
||||
do {
|
||||
status = dmub_srv_wait_for_pending(dmub, 100000);
|
||||
status = dmub_srv_wait_for_pending(dmub, MAX_WAIT_US);
|
||||
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
|
||||
return status == DMUB_STATUS_OK;
|
||||
|
|
@ -104,7 +113,7 @@ void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
|
|||
status = dmub_srv_clear_inbox0_ack(dmub);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error clearing INBOX0 ack: status=%d\n", status);
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,10 +123,10 @@ void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dc_dmub_srv)
|
|||
struct dc_context *dc_ctx = dc_dmub_srv->ctx;
|
||||
enum dmub_status status = DMUB_STATUS_OK;
|
||||
|
||||
status = dmub_srv_wait_for_inbox0_ack(dmub, 100000);
|
||||
status = dmub_srv_wait_for_inbox0_ack(dmub, MAX_WAIT_US);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error waiting for INBOX0 HW Lock Ack\n");
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +140,7 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
|
|||
status = dmub_srv_send_inbox0_cmd(dmub, data);
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
DC_ERROR("Error sending INBOX0 cmd\n");
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +162,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
|
|||
for (i = 0 ; i < count; i++) {
|
||||
/* confirm no messages pending */
|
||||
do {
|
||||
status = dmub_srv_wait_for_idle(dmub, 100000);
|
||||
status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
|
||||
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
|
||||
|
||||
/* queue command */
|
||||
|
|
@ -169,7 +178,7 @@ static bool dc_dmub_srv_reg_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_s
|
|||
if (status != DMUB_STATUS_OK) {
|
||||
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);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -208,7 +217,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
|
|||
return false;
|
||||
|
||||
do {
|
||||
status = dmub_srv_wait_for_inbox_free(dmub, 100000, count - i);
|
||||
status = dmub_srv_wait_for_inbox_free(dmub, MAX_WAIT_US, count - i);
|
||||
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
|
||||
|
||||
/* Requeue the command. */
|
||||
|
|
@ -218,7 +227,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
|
|||
if (status != DMUB_STATUS_OK) {
|
||||
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);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -228,7 +237,7 @@ static bool dc_dmub_srv_fb_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_sr
|
|||
if (status != DMUB_STATUS_OK) {
|
||||
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);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -271,7 +280,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
|
|||
// Wait for DMUB to process command
|
||||
if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
|
||||
do {
|
||||
status = dmub_srv_wait_for_idle(dmub, 100000);
|
||||
status = dmub_srv_wait_for_idle(dmub, MAX_WAIT_US);
|
||||
} while (dc_dmub_srv->ctx->dc->debug.disable_timeout && status != DMUB_STATUS_OK);
|
||||
|
||||
if (status != DMUB_STATUS_OK) {
|
||||
|
|
@ -282,7 +291,7 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
|
|||
dmub->debug.timeout_info.timeout_cmd = *cmd_list;
|
||||
dmub->debug.timeout_info.timestamp = dm_get_timestamp(dc_dmub_srv->ctx);
|
||||
}
|
||||
dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
|
||||
dc_dmub_srv_handle_failure(dc_dmub_srv);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -964,6 +964,13 @@ struct display_endpoint_id {
|
|||
enum display_endpoint_type ep_type;
|
||||
};
|
||||
|
||||
enum dc_panel_type {
|
||||
PANEL_TYPE_NONE = 0, // UNKONWN, not determined yet
|
||||
PANEL_TYPE_LCD = 1,
|
||||
PANEL_TYPE_OLED = 2,
|
||||
PANEL_TYPE_MINILED = 3,
|
||||
};
|
||||
|
||||
enum backlight_control_type {
|
||||
BACKLIGHT_CONTROL_PWM = 0,
|
||||
BACKLIGHT_CONTROL_VESA_AUX = 1,
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz);
|
|||
|
||||
bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable);
|
||||
|
||||
void dm_helpers_dmu_timeout(struct dc_context *ctx);
|
||||
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us);
|
||||
|
||||
// 0x1 = Result_OK, 0xFE = Result_UnkmownCmd, 0x0 = Status_Busy
|
||||
|
|
|
|||
|
|
@ -1157,7 +1157,7 @@ static bool setup_dsc_config(
|
|||
if (!is_dsc_possible)
|
||||
goto done;
|
||||
|
||||
/* increase miniumum slice count to meet sink slice width limitations */
|
||||
/* increase minimum slice count to meet sink slice width limitations */
|
||||
min_slices_h = dc_fixpt_ceil(dc_fixpt_max(
|
||||
dc_fixpt_div_int(dc_fixpt_from_int(pic_width), dsc_common_caps.max_slice_width), // sink min
|
||||
dc_fixpt_from_int(min_slices_h))); // source min
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include "dc_state_priv.h"
|
||||
#include "dpcd_defs.h"
|
||||
#include "dsc.h"
|
||||
#include "dc_dp_types.h"
|
||||
/* include DCE11 register header files */
|
||||
#include "dce/dce_11_0_d.h"
|
||||
#include "dce/dce_11_0_sh_mask.h"
|
||||
|
|
@ -1759,20 +1760,25 @@ static void power_down_encoders(struct dc *dc)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < dc->link_count; i++) {
|
||||
enum signal_type signal = dc->links[i]->connector_signal;
|
||||
|
||||
dc->link_srv->blank_dp_stream(dc->links[i], false);
|
||||
struct dc_link *link = dc->links[i];
|
||||
struct link_encoder *link_enc = link->link_enc;
|
||||
enum signal_type signal = link->connector_signal;
|
||||
|
||||
dc->link_srv->blank_dp_stream(link, false);
|
||||
if (signal != SIGNAL_TYPE_EDP)
|
||||
signal = SIGNAL_TYPE_NONE;
|
||||
|
||||
if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY)
|
||||
dc->links[i]->link_enc->funcs->disable_output(
|
||||
dc->links[i]->link_enc, signal);
|
||||
if (link->ep_type == DISPLAY_ENDPOINT_PHY)
|
||||
link_enc->funcs->disable_output(link_enc, signal);
|
||||
|
||||
dc->links[i]->link_status.link_active = false;
|
||||
memset(&dc->links[i]->cur_link_settings, 0,
|
||||
sizeof(dc->links[i]->cur_link_settings));
|
||||
if (link->fec_state == dc_link_fec_enabled) {
|
||||
link_enc->funcs->fec_set_enable(link_enc, false);
|
||||
link_enc->funcs->fec_set_ready(link_enc, false);
|
||||
link->fec_state = dc_link_fec_not_ready;
|
||||
}
|
||||
|
||||
link->link_status.link_active = false;
|
||||
memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3145,8 +3145,6 @@ void dcn20_fpga_init_hw(struct dc *dc)
|
|||
REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
|
||||
REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
|
||||
|
||||
hws->funcs.dccg_init(hws);
|
||||
|
||||
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
|
||||
REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
|
||||
if (REG(REFCLK_CNTL))
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ static const struct hwseq_private_funcs dcn30_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_blend_lut = dcn30_set_blend_lut,
|
||||
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ static const struct hwseq_private_funcs dcn301_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_blend_lut = dcn30_set_blend_lut,
|
||||
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -546,8 +546,22 @@ static void dcn31_reset_back_end_for_pipe(
|
|||
if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
|
||||
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
|
||||
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
|
||||
/*
|
||||
* TODO - convert symclk_ref_cnts for otg to a bit map to solve
|
||||
* the case where the same symclk is shared across multiple otg
|
||||
* instances
|
||||
*/
|
||||
if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
|
||||
pipe_ctx->stream->link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
link->phy_state.symclk_ref_cnts.otg = 0;
|
||||
|
||||
if (pipe_ctx->top_pipe == NULL) {
|
||||
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
|
||||
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
|
||||
|
||||
link_hwss->disable_link_output(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
|
||||
link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
set_drr_and_clear_adjust_pending(pipe_ctx, pipe_ctx->stream, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ static const struct hwseq_private_funcs dcn31_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_blend_lut = dcn30_set_blend_lut,
|
||||
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
|
||||
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_blend_lut = dcn30_set_blend_lut,
|
||||
.set_shaper_3dlut = dcn20_set_shaper_3dlut,
|
||||
.setup_hpo_hw_control = dcn31_setup_hpo_hw_control,
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_mcm_luts = dcn32_set_mcm_luts,
|
||||
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
|
||||
.update_force_pstate = dcn32_update_force_pstate,
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_mcm_luts = dcn32_set_mcm_luts,
|
||||
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
|
||||
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
|
|||
.set_hdr_multiplier = dcn10_set_hdr_multiplier,
|
||||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_mcm_luts = dcn32_set_mcm_luts,
|
||||
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
|
||||
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
|
||||
|
|
|
|||
|
|
@ -948,7 +948,7 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
|
|||
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
|
||||
struct dc *dc = pipe_ctx->stream->ctx->dc;
|
||||
struct dccg *dccg = dc->res_pool->dccg;
|
||||
enum phyd32clk_clock_source phyd32clk;
|
||||
enum phyd32clk_clock_source phyd32clk = PHYD32CLKA;
|
||||
int dp_hpo_inst = 0;
|
||||
unsigned int tmds_div = PIXEL_RATE_DIV_NA;
|
||||
unsigned int unused_div = PIXEL_RATE_DIV_NA;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
|
|||
.verify_allow_pstate_change_high = dcn10_verify_allow_pstate_change_high,
|
||||
.verify_allow_pstate_change_high_sequence = dcn401_verify_allow_pstate_change_high_sequence,
|
||||
.wait_for_blank_complete = dcn20_wait_for_blank_complete,
|
||||
.dccg_init = dcn20_dccg_init,
|
||||
.set_mcm_luts = dcn401_set_mcm_luts,
|
||||
.program_mall_pipe_config = dcn32_program_mall_pipe_config,
|
||||
.program_mall_pipe_config_sequence = dcn401_program_mall_pipe_config_sequence,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct drr_params;
|
|||
struct dc_underflow_debug_data;
|
||||
struct dsc_optc_config;
|
||||
struct vm_system_aperture_param;
|
||||
|
||||
struct memory_qos;
|
||||
struct subvp_pipe_control_lock_fast_params {
|
||||
struct dc *dc;
|
||||
bool lock;
|
||||
|
|
@ -1289,40 +1289,14 @@ struct hw_sequencer_funcs {
|
|||
struct dc_underflow_debug_data *out_data);
|
||||
|
||||
/**
|
||||
* measure_peak_bw_mbps - Measure actual peak bandwidth in Mbps
|
||||
* measure_memory_qos - Measure memory QoS metrics
|
||||
* @dc: DC structure
|
||||
* @qos: Pointer to memory_qos struct to populate with measured values
|
||||
*
|
||||
* Returns the measured peak bandwidth value in Mbps from hardware
|
||||
* performance counters or registers.
|
||||
* Populates the provided memory_qos struct with peak bandwidth, average bandwidth,
|
||||
* max latency, min latency, and average latency from hardware performance counters.
|
||||
*/
|
||||
uint32_t (*measure_peak_bw_mbps)(struct dc *dc);
|
||||
|
||||
/**
|
||||
* measure_avg_bw_mbps - Measure actual average bandwidth in Mbps
|
||||
* @dc: DC structure
|
||||
*
|
||||
* Returns the measured average bandwidth value in Mbps from hardware
|
||||
* performance counters or registers.
|
||||
*/
|
||||
uint32_t (*measure_avg_bw_mbps)(struct dc *dc);
|
||||
|
||||
/**
|
||||
* measure_max_latency_ns - Measure actual maximum latency in nanoseconds
|
||||
* @dc: DC structure
|
||||
*
|
||||
* Returns the measured maximum latency value in nanoseconds from hardware
|
||||
* performance counters or registers.
|
||||
*/
|
||||
uint32_t (*measure_max_latency_ns)(struct dc *dc);
|
||||
|
||||
/**
|
||||
* measure_avg_latency_ns - Measure actual average latency in nanoseconds
|
||||
* @dc: DC structure
|
||||
*
|
||||
* Returns the measured average latency value in nanoseconds from hardware
|
||||
* performance counters or registers.
|
||||
*/
|
||||
uint32_t (*measure_avg_latency_ns)(struct dc *dc);
|
||||
void (*measure_memory_qos)(struct dc *dc, struct memory_qos *qos);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -704,4 +704,12 @@ struct dc_bounding_box_max_clk {
|
|||
int max_phyclk_mhz;
|
||||
};
|
||||
|
||||
struct memory_qos {
|
||||
uint32_t peak_bw_mbps;
|
||||
uint32_t avg_bw_mbps;
|
||||
uint32_t max_latency_ns;
|
||||
uint32_t min_latency_ns;
|
||||
uint32_t avg_latency_ns;
|
||||
};
|
||||
|
||||
#endif /* _CORE_TYPES_H_ */
|
||||
|
|
|
|||
|
|
@ -254,30 +254,38 @@ struct hubbub_funcs {
|
|||
bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
|
||||
void (*dchvm_init)(struct hubbub *hubbub);
|
||||
|
||||
/* Performance monitoring related functions */
|
||||
struct hubbub_perfmon_funcs {
|
||||
void (*reset)(struct hubbub *hubbub);
|
||||
void (*start_measuring_max_memory_latency_ns)(
|
||||
void (*start_measuring_memory_latencies)(
|
||||
struct hubbub *hubbub);
|
||||
uint32_t (*get_max_memory_latency_ns)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz, uint32_t *sample_count);
|
||||
void (*start_measuring_average_memory_latency_ns)(
|
||||
uint32_t (*get_memory_latencies_ns)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz, uint32_t *min_latency_ns,
|
||||
uint32_t *max_latency_ns, uint32_t *avg_latency_ns);
|
||||
void (*start_measuring_urgent_assertion_count)(
|
||||
struct hubbub *hubbub);
|
||||
uint32_t (*get_average_memory_latency_ns)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz, uint32_t *sample_count);
|
||||
void (*start_measuring_urgent_ramp_latency_ns)(
|
||||
bool (*get_urgent_assertion_count)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz,
|
||||
uint32_t *assertion_count,
|
||||
uint32_t *deassertion_count,
|
||||
uint32_t *timestamp_us);
|
||||
void (*start_measuring_urgent_ramp_latency)(
|
||||
struct hubbub *hubbub,
|
||||
const struct hubbub_urgent_latency_params *params);
|
||||
uint32_t (*get_urgent_ramp_latency_ns)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz);
|
||||
void (*start_measuring_unbounded_bandwidth_mbps)(
|
||||
void (*start_measuring_unbounded_bandwidth)(
|
||||
struct hubbub *hubbub);
|
||||
uint32_t (*get_unbounded_bandwidth_mbps)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz, uint32_t *duration_ns);
|
||||
void (*start_measuring_average_bandwidth_mbps)(
|
||||
void (*start_measuring_in_order_bandwidth)(
|
||||
struct hubbub *hubbub);
|
||||
uint32_t (*get_average_bandwidth_mbps)(struct hubbub *hubbub,
|
||||
uint32_t (*get_in_order_bandwidth_mbps)(struct hubbub *hubbub,
|
||||
uint32_t refclk_mhz, uint32_t min_duration_ns,
|
||||
uint32_t *duration_ns);
|
||||
void (*start_measuring_prefetch_data_size)(
|
||||
struct hubbub *hubbub);
|
||||
uint32_t (*get_prefetch_data_size)(struct hubbub *hubbub);
|
||||
} perfmon;
|
||||
|
||||
struct hubbub_qos_funcs {
|
||||
|
|
|
|||
|
|
@ -156,13 +156,23 @@ bool dp_pr_get_panel_inst(const struct dc *dc,
|
|||
const struct dc_link *link,
|
||||
unsigned int *inst_out)
|
||||
{
|
||||
if (dc_is_embedded_signal(link->connector_signal)) {
|
||||
/* TODO: just get edp link panel inst for now, fix it */
|
||||
return dc_get_edp_link_panel_inst(dc, link, inst_out);
|
||||
} else if (dc_is_dp_sst_signal(link->connector_signal)) {
|
||||
/* TODO: just set to 1 for now, fix it */
|
||||
*inst_out = 1;
|
||||
return true;
|
||||
if (!dc || !link || !inst_out)
|
||||
return false;
|
||||
|
||||
if (!dc_is_dp_sst_signal(link->connector_signal)) /* only supoprt DP sst (eDP included) for now */
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < MAX_PIPES; i++) {
|
||||
if (dc->current_state->res_ctx.pipe_ctx[i].stream &&
|
||||
dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
|
||||
/* *inst_out is equal to otg number */
|
||||
if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg)
|
||||
*inst_out = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst;
|
||||
else
|
||||
*inst_out = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -280,13 +290,13 @@ bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_da
|
|||
return false;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data));
|
||||
|
||||
cmd.pr_update_state.header.type = DMUB_CMD__PR;
|
||||
cmd.pr_update_state.header.sub_type = DMUB_CMD__PR_UPDATE_STATE;
|
||||
cmd.pr_update_state.header.payload_bytes = sizeof(struct dmub_cmd_pr_update_state_data);
|
||||
cmd.pr_update_state.data.panel_inst = panel_inst;
|
||||
|
||||
memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data));
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -301,13 +311,13 @@ bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_
|
|||
return false;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data));
|
||||
|
||||
cmd.pr_general_cmd.header.type = DMUB_CMD__PR;
|
||||
cmd.pr_general_cmd.header.sub_type = DMUB_CMD__PR_GENERAL_CMD;
|
||||
cmd.pr_general_cmd.header.payload_bytes = sizeof(struct dmub_cmd_pr_general_cmd_data);
|
||||
cmd.pr_general_cmd.data.panel_inst = panel_inst;
|
||||
|
||||
memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data));
|
||||
|
||||
dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "dce/dmub_replay.h"
|
||||
#include "abm.h"
|
||||
#include "resource.h"
|
||||
#include "link_dp_panel_replay.h"
|
||||
#define DC_LOGGER \
|
||||
link->ctx->logger
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
|
@ -942,7 +943,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
|
|||
if (replay == NULL && force_static)
|
||||
return false;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
/* Set power optimization flag */
|
||||
|
|
@ -973,7 +974,7 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
|
|||
unsigned int panel_inst;
|
||||
enum replay_state pr_state = REPLAY_STATE_0;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
if (replay != NULL && link->replay_settings.replay_feature_enabled)
|
||||
|
|
@ -1020,7 +1021,7 @@ bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_stat
|
|||
if (!replay)
|
||||
return false;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
|
||||
|
|
@ -1099,7 +1100,7 @@ bool edp_send_replay_cmd(struct dc_link *link,
|
|||
|
||||
DC_LOGGER_INIT(link->ctx->logger);
|
||||
|
||||
if (dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
cmd_data->panel_inst = panel_inst;
|
||||
else {
|
||||
DC_LOG_DC("%s(): get edp panel inst fail ", __func__);
|
||||
|
|
@ -1120,7 +1121,7 @@ bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal, uin
|
|||
if (!replay)
|
||||
return false;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
if (coasting_vtotal && (link->replay_settings.coasting_vtotal != coasting_vtotal ||
|
||||
|
|
@ -1140,7 +1141,7 @@ bool edp_replay_residency(const struct dc_link *link,
|
|||
struct dmub_replay *replay = dc->res_pool->replay;
|
||||
unsigned int panel_inst;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
if (!residency)
|
||||
|
|
@ -1161,7 +1162,7 @@ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
|
|||
struct dmub_replay *replay = dc->res_pool->replay;
|
||||
unsigned int panel_inst;
|
||||
|
||||
if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
|
||||
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
|
||||
return false;
|
||||
|
||||
/* Only both power and coasting vtotal changed, this func could return true */
|
||||
|
|
|
|||
|
|
@ -1635,9 +1635,9 @@ union dmub_inbox0_cmd_lock_hw {
|
|||
uint32_t lock_dig: 1;
|
||||
uint32_t triple_buffer_lock: 1;
|
||||
|
||||
uint32_t lock: 1; /**< Lock */
|
||||
uint32_t lock: 1; /**< Lock */
|
||||
uint32_t should_release: 1; /**< Release */
|
||||
uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
|
||||
uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
|
||||
} bits;
|
||||
uint32_t all;
|
||||
};
|
||||
|
|
@ -2658,7 +2658,6 @@ struct dmub_cmd_fams2_global_config {
|
|||
|
||||
union dmub_cmd_fams2_config {
|
||||
struct dmub_cmd_fams2_global_config global;
|
||||
// coverity[cert_dcl37_c_violation:FALSE] errno.h, stddef.h, stdint.h not included in atombios.h
|
||||
struct dmub_fams2_stream_static_state stream; //v0
|
||||
union {
|
||||
struct dmub_fams2_cmd_stream_static_base_state base;
|
||||
|
|
@ -3678,7 +3677,7 @@ struct dmub_cmd_psr_copy_settings_data {
|
|||
/**
|
||||
* @ rate_control_caps : Indicate FreeSync PSR Sink Capabilities
|
||||
*/
|
||||
uint8_t rate_control_caps ;
|
||||
uint8_t rate_control_caps;
|
||||
/*
|
||||
* Force PSRSU always doing full frame update
|
||||
*/
|
||||
|
|
@ -5164,8 +5163,8 @@ enum dmub_cmd_lsdma_type {
|
|||
*/
|
||||
DMUB_CMD__LSDMA_LINEAR_COPY = 1,
|
||||
/**
|
||||
* LSDMA copies data from source to destination linearly in sub window
|
||||
*/
|
||||
* LSDMA copies data from source to destination linearly in sub window
|
||||
*/
|
||||
DMUB_CMD__LSDMA_LINEAR_SUB_WINDOW_COPY = 2,
|
||||
/**
|
||||
* Send the tiled-to-tiled copy command
|
||||
|
|
|
|||
|
|
@ -984,10 +984,13 @@ void set_replay_frame_skip_number(struct dc_link *link,
|
|||
uint32_t *frame_skip_number_array = NULL;
|
||||
uint32_t frame_skip_number = 0;
|
||||
|
||||
if (link == NULL)
|
||||
return;
|
||||
|
||||
if (false == link->replay_settings.config.frame_skip_supported)
|
||||
return;
|
||||
|
||||
if (link == NULL || flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
|
||||
if (flicker_free_refresh_rate_mhz == 0 || coasting_vtotal_refresh_rate_mhz == 0)
|
||||
return;
|
||||
|
||||
if (is_defer)
|
||||
|
|
|
|||
|
|
@ -1569,7 +1569,7 @@ int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev,
|
|||
int ret = 0;
|
||||
|
||||
if (!pp_funcs->get_power_limit)
|
||||
return -ENODATA;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle,
|
||||
|
|
|
|||
|
|
@ -3878,7 +3878,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
|
|||
attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr))
|
||||
return 0;
|
||||
|
||||
/* only Vangogh has fast PPT limit and power labels */
|
||||
/* only a few GPUs have fast PPT limit and power labels */
|
||||
if ((attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr ||
|
||||
attr == &sensor_dev_attr_power2_cap.dev_attr.attr ||
|
||||
|
|
|
|||
|
|
@ -2273,8 +2273,6 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
|
|||
if (scaling_factor == 0)
|
||||
return -EINVAL;
|
||||
|
||||
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
|
||||
|
||||
ret = si_calculate_adjusted_tdp_limits(adev,
|
||||
false, /* ??? */
|
||||
adev->pm.dpm.tdp_adjustment,
|
||||
|
|
@ -2283,6 +2281,12 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adev->pdev->device == 0x6611 && adev->pdev->revision == 0x87) {
|
||||
/* Workaround buggy powertune on Radeon 430 and 520. */
|
||||
tdp_limit = 32;
|
||||
near_tdp_limit = 28;
|
||||
}
|
||||
|
||||
smc_table->dpm2Params.TDPLimit =
|
||||
cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
|
||||
smc_table->dpm2Params.NearTDPLimit =
|
||||
|
|
@ -2328,16 +2332,8 @@ static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,
|
|||
|
||||
if (ni_pi->enable_power_containment) {
|
||||
SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
|
||||
u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
|
||||
int ret;
|
||||
|
||||
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
|
||||
|
||||
smc_table->dpm2Params.NearTDPLimit =
|
||||
cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
|
||||
smc_table->dpm2Params.SafePowerLimit =
|
||||
cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
|
||||
|
||||
ret = amdgpu_si_copy_bytes_to_smc(adev,
|
||||
(si_pi->state_table_start +
|
||||
offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
|
||||
|
|
@ -3473,10 +3469,15 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
|
|||
(adev->pdev->revision == 0x80) ||
|
||||
(adev->pdev->revision == 0x81) ||
|
||||
(adev->pdev->revision == 0x83) ||
|
||||
(adev->pdev->revision == 0x87) ||
|
||||
(adev->pdev->revision == 0x87 &&
|
||||
adev->pdev->device != 0x6611) ||
|
||||
(adev->pdev->device == 0x6604) ||
|
||||
(adev->pdev->device == 0x6605)) {
|
||||
max_sclk = 75000;
|
||||
} else if (adev->pdev->revision == 0x87 &&
|
||||
adev->pdev->device == 0x6611) {
|
||||
/* Radeon 430 and 520 */
|
||||
max_sclk = 78000;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7600,12 +7601,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
|
|||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
|
||||
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
|
||||
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
|
||||
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
|
||||
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -7617,12 +7618,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
|
|||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
|
||||
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
|
||||
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
|
||||
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
|
||||
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -956,7 +956,7 @@ void smu_v13_0_12_get_gpu_metrics(struct smu_context *smu, void **table,
|
|||
gpu_metrics->gfx_below_host_limit_total_acc
|
||||
[i] = SMUQ10_ROUND(
|
||||
metrics->GfxclkBelowHostLimitTotalAcc[inst]);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
gpu_metrics->xgmi_link_width = metrics->XgmiWidth;
|
||||
|
|
|
|||
|
|
@ -121,8 +121,9 @@ int radeon_vce_init(struct radeon_device *rdev)
|
|||
if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_INFO("Found VCE firmware/feedback version %d.%d.%d / %d!\n",
|
||||
start, mid, end, rdev->vce.fb_version);
|
||||
drm_info(&rdev->ddev,
|
||||
"Found VCE firmware/feedback version %d.%d.%d / %d!\n",
|
||||
start, mid, end, rdev->vce.fb_version);
|
||||
|
||||
rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue