Merge tag 'drm-fixes-2026-04-03' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fixes from Dave Airlie: "Hopefully no Easter eggs in this bunch of fixes. Usual stuff across the amd/intel with some misc bits. Thanks to Thorsten and Alex for making sure a regression fix that was hanging around in process land finally made it in, that is probably the biggest change in here. core: - revert unplug/framebuffer fix as it caused problems - compat ioctl speculation fix bridge: - refcounting fix sysfb: - error handling fix amdgpu: - fix renoir audio regression - UserQ fixes - PASID handling fix - S4 fix for smu11 chips - Misc small fixes amdkfd: - Non-4K page fixes i915: - Fix for #12045: Huawei Matebook E (DRR-WXX): Persistent Black Screen on Boot with i915 and Gen11: Modesetting and Backlight Control Malfunction - Fix for #15826: i915: Raptor Lake-P [UHD Graphics] display flicker/corruption on eDP panel - Use crtc_state->enhanced_framing properly on ivb/hsw CPU eDP xe: - uapi: Accept canonical GPU addresses in xe_vm_madvise_ioctl - Disallow writes to read-only VMAs - PXP fixes - Disable garbage collector work item on SVM close - void memory allocations in xe_device_declare_wedged qaic: - hang fix ast: - initialisation fix" * tag 'drm-fixes-2026-04-03' of https://gitlab.freedesktop.org/drm/kernel: (28 commits) drm/amd/display: Wire up dcn10_dio_construct() for all pre-DCN401 generations drm/ioc32: stop speculation on the drm_compat_ioctl path drm/sysfb: Fix efidrm error handling and memory type mismatch drm/i915/dp: Use crtc_state->enhanced_framing properly on ivb/hsw CPU eDP drm/i915/cdclk: Do the full CDCLK dance for min_voltage_level changes drm/amdkfd: Fix queue preemption/eviction failures by aligning control stack size to GPU page size drm/amdgpu: Fix wait after reset sequence in S4 drm/amd/display: Fix NULL pointer dereference in dcn401_init_hw() drm/amdgpu: Change AMDGPU_VA_RESERVED_TRAP_SIZE to 64KB drm/amdgpu/userq: fix memory leak in MQD creation error paths drm/amd: Fix MQD and control stack alignment for non-4K drm/amdkfd: Align expected_queue_size to PAGE_SIZE drm/amdgpu: fix the idr allocation flags drm/amdgpu: validate doorbell_offset in user queue creation drm/amdgpu/pm: drop SMU driver if version not matched messages drm/xe: Avoid memory allocations in xe_device_declare_wedged() drm/xe: Disable garbage collector work item on SVM close drm/xe/pxp: Don't allow PXP on older PTL GSC FWs drm/xe/pxp: Clear restart flag in pxp_start after jumping back drm/xe/pxp: Remove incorrect handling of impossible state during suspend ...
This commit is contained in:
commit
60d9212c69
48 files changed
+1013
-108
No files matched your search
@@ -914,7 +914,7 @@ static int decode_deactivate(struct qaic_device *qdev, void *trans, u32 *msg_len
|
||||
*/
|
||||
return -ENODEV;
|
||||
|
||||
if (status) {
|
||||
if (usr && status) {
|
||||
/*
|
||||
* Releasing resources failed on the device side, which puts
|
||||
* us in a bind since they may still be in use, so enable the
|
||||
@@ -1109,6 +1109,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
|
||||
mutex_lock(&qdev->cntl_mutex);
|
||||
if (!list_empty(&elem.list))
|
||||
list_del(&elem.list);
|
||||
/* resp_worker() processed the response but the wait was interrupted */
|
||||
else if (ret == -ERESTARTSYS)
|
||||
ret = 0;
|
||||
if (!ret && !elem.buf)
|
||||
ret = -ETIMEDOUT;
|
||||
else if (ret > 0 && !elem.buf)
|
||||
@@ -1419,9 +1422,49 @@ static void resp_worker(struct work_struct *work)
|
||||
}
|
||||
mutex_unlock(&qdev->cntl_mutex);
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
/*
|
||||
* The user might have gone away at this point without waiting
|
||||
* for QAIC_TRANS_DEACTIVATE_FROM_DEV transaction coming from
|
||||
* the device. If this is not handled correctly, the host will
|
||||
* not know that the DBC[n] has been freed on the device.
|
||||
* Due to this failure in synchronization between the device and
|
||||
* the host, if another user requests to activate a network, and
|
||||
* the device assigns DBC[n] again, save_dbc_buf() will hang,
|
||||
* waiting for dbc[n]->in_use to be set to false, which will not
|
||||
* happen unless the qaic_dev_reset_clean_local_state() gets
|
||||
* called by resetting the device (or re-inserting the module).
|
||||
*
|
||||
* As a solution, we look for QAIC_TRANS_DEACTIVATE_FROM_DEV
|
||||
* transactions in the message before disposing of it, then
|
||||
* handle releasing the DBC resources.
|
||||
*
|
||||
* Since the user has gone away, if the device could not
|
||||
* deactivate the network (status != 0), there is no way to
|
||||
* enable and reassign the DBC to the user. We can put trust in
|
||||
* the device that it will release all the active DBCs in
|
||||
* response to the QAIC_TRANS_TERMINATE_TO_DEV transaction,
|
||||
* otherwise, the user can issue an soc_reset to the device.
|
||||
*/
|
||||
u32 msg_count = le32_to_cpu(msg->hdr.count);
|
||||
u32 msg_len = le32_to_cpu(msg->hdr.len);
|
||||
u32 len = 0;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < msg_count && len < msg_len; ++j) {
|
||||
struct wire_trans_hdr *trans_hdr;
|
||||
|
||||
trans_hdr = (struct wire_trans_hdr *)(msg->data + len);
|
||||
if (le32_to_cpu(trans_hdr->type) == QAIC_TRANS_DEACTIVATE_FROM_DEV) {
|
||||
if (decode_deactivate(qdev, trans_hdr, &len, NULL))
|
||||
len += le32_to_cpu(trans_hdr->len);
|
||||
} else {
|
||||
len += le32_to_cpu(trans_hdr->len);
|
||||
}
|
||||
}
|
||||
/* request must have timed out, drop packet */
|
||||
kfree(msg);
|
||||
}
|
||||
|
||||
kfree(resp);
|
||||
}
|
||||
|
||||
@@ -2703,8 +2703,12 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (amdgpu_acpi_should_gpu_reset(adev))
|
||||
return amdgpu_asic_reset(adev);
|
||||
if (amdgpu_acpi_should_gpu_reset(adev)) {
|
||||
amdgpu_device_lock_reset_domain(adev->reset_domain);
|
||||
r = amdgpu_asic_reset(adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -403,6 +403,50 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_map_gfx9_mqd - map mqd and ctrl_stack dma_addresses into GART entries
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @offset: offset into the GPU's gart aperture
|
||||
* @pages: number of pages to bind
|
||||
* @dma_addr: DMA addresses of pages
|
||||
* @flags: page table entry flags
|
||||
*
|
||||
* Map the MQD and control stack addresses into GART entries with the correct
|
||||
* memory types on gfxv9. The MQD occupies the first 4KB and is followed by
|
||||
* the control stack. The MQD uses UC (uncached) memory, while the control stack
|
||||
* uses NC (non-coherent) memory.
|
||||
*/
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags)
|
||||
{
|
||||
uint64_t page_base;
|
||||
unsigned int i, j, t;
|
||||
int idx;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
void *dst;
|
||||
|
||||
if (!adev->gart.ptr)
|
||||
return;
|
||||
|
||||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
t = offset / AMDGPU_GPU_PAGE_SIZE;
|
||||
dst = adev->gart.ptr;
|
||||
for (i = 0; i < pages; i++) {
|
||||
page_base = dma_addr[i];
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
if ((i == 0) && (j == 0))
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, flags);
|
||||
else
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, t, page_base, ctrl_flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gart_bind - bind pages into the gart page table
|
||||
*
|
||||
|
||||
@@ -62,6 +62,8 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset,
|
||||
void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags,
|
||||
void *dst);
|
||||
void amdgpu_gart_map_gfx9_mqd(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset,
|
||||
int pages, dma_addr_t *dma_addr, uint64_t flags);
|
||||
void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
|
||||
@@ -68,8 +68,11 @@ int amdgpu_pasid_alloc(unsigned int bits)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&amdgpu_pasid_idr_lock);
|
||||
/* TODO: Need to replace the idr with an xarry, and then
|
||||
* handle the internal locking with ATOMIC safe paths.
|
||||
*/
|
||||
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
|
||||
1U << bits, GFP_KERNEL);
|
||||
1U << bits, GFP_ATOMIC);
|
||||
spin_unlock(&amdgpu_pasid_idr_lock);
|
||||
|
||||
if (pasid >= 0)
|
||||
|
||||
@@ -853,25 +853,15 @@ static void amdgpu_ttm_gart_bind_gfx9_mqd(struct amdgpu_device *adev,
|
||||
int num_xcc = max(1U, adev->gfx.num_xcc_per_xcp);
|
||||
uint64_t page_idx, pages_per_xcc;
|
||||
int i;
|
||||
uint64_t ctrl_flags = AMDGPU_PTE_MTYPE_VG10(flags, AMDGPU_MTYPE_NC);
|
||||
|
||||
pages_per_xcc = total_pages;
|
||||
do_div(pages_per_xcc, num_xcc);
|
||||
|
||||
for (i = 0, page_idx = 0; i < num_xcc; i++, page_idx += pages_per_xcc) {
|
||||
/* MQD page: use default flags */
|
||||
amdgpu_gart_bind(adev,
|
||||
amdgpu_gart_map_gfx9_mqd(adev,
|
||||
gtt->offset + (page_idx << PAGE_SHIFT),
|
||||
1, >t->ttm.dma_address[page_idx], flags);
|
||||
/*
|
||||
* Ctrl pages - modify the memory type to NC (ctrl_flags) from
|
||||
* the second page of the BO onward.
|
||||
*/
|
||||
amdgpu_gart_bind(adev,
|
||||
gtt->offset + ((page_idx + 1) << PAGE_SHIFT),
|
||||
pages_per_xcc - 1,
|
||||
>t->ttm.dma_address[page_idx + 1],
|
||||
ctrl_flags);
|
||||
pages_per_xcc, >t->ttm.dma_address[page_idx],
|
||||
flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -600,6 +600,13 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
|
||||
goto unpin_bo;
|
||||
}
|
||||
|
||||
/* Validate doorbell_offset is within the doorbell BO */
|
||||
if ((u64)db_info->doorbell_offset * db_size + db_size >
|
||||
amdgpu_bo_size(db_obj->obj)) {
|
||||
r = -EINVAL;
|
||||
goto unpin_bo;
|
||||
}
|
||||
|
||||
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
|
||||
db_info->doorbell_offset, db_size);
|
||||
drm_dbg_driver(adev_to_drm(uq_mgr->adev),
|
||||
|
||||
@@ -173,7 +173,7 @@ struct amdgpu_bo_vm;
|
||||
#define AMDGPU_VA_RESERVED_SEQ64_SIZE (2ULL << 20)
|
||||
#define AMDGPU_VA_RESERVED_SEQ64_START(adev) (AMDGPU_VA_RESERVED_CSA_START(adev) \
|
||||
- AMDGPU_VA_RESERVED_SEQ64_SIZE)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_SIZE (2ULL << 12)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_SIZE (1ULL << 16)
|
||||
#define AMDGPU_VA_RESERVED_TRAP_START(adev) (AMDGPU_VA_RESERVED_SEQ64_START(adev) \
|
||||
- AMDGPU_VA_RESERVED_TRAP_SIZE)
|
||||
#define AMDGPU_VA_RESERVED_BOTTOM (1ULL << 16)
|
||||
|
||||
@@ -324,8 +324,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
|
||||
2048);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(compute_mqd);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
userq_props->eop_gpu_addr = compute_mqd->eop_va;
|
||||
userq_props->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_NORMAL;
|
||||
@@ -365,12 +367,16 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
|
||||
shadow_info.shadow_size);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
|
||||
shadow_info.csa_size);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_gfx_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
kfree(mqd_gfx_v11);
|
||||
} else if (queue->queue_type == AMDGPU_HW_IP_DMA) {
|
||||
@@ -390,8 +396,10 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
|
||||
}
|
||||
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
|
||||
32);
|
||||
if (r)
|
||||
if (r) {
|
||||
kfree(mqd_sdma_v11);
|
||||
goto free_mqd;
|
||||
}
|
||||
|
||||
userq_props->csa_addr = mqd_sdma_v11->csa_va;
|
||||
kfree(mqd_sdma_v11);
|
||||
|
||||
@@ -170,7 +170,8 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
|
||||
int retry_loop;
|
||||
|
||||
/* For a reset done at the end of S3, only wait for TOS to be unloaded */
|
||||
if (adev->in_s3 && !(adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev))
|
||||
if ((adev->in_s4 || adev->in_s3) && !(adev->flags & AMD_IS_APU) &&
|
||||
amdgpu_in_reset(adev))
|
||||
return psp_v11_wait_for_tos_unload(psp);
|
||||
|
||||
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
|
||||
|
||||
@@ -42,9 +42,16 @@ static uint64_t mqd_stride_v9(struct mqd_manager *mm,
|
||||
struct queue_properties *q)
|
||||
{
|
||||
if (mm->dev->kfd->cwsr_enabled &&
|
||||
q->type == KFD_QUEUE_TYPE_COMPUTE)
|
||||
return ALIGN(q->ctl_stack_size, PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE);
|
||||
q->type == KFD_QUEUE_TYPE_COMPUTE) {
|
||||
|
||||
/* On gfxv9, the MQD resides in the first 4K page,
|
||||
* followed by the control stack. Align both to
|
||||
* AMDGPU_GPU_PAGE_SIZE to maintain the required 4K boundary.
|
||||
*/
|
||||
|
||||
return ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE);
|
||||
}
|
||||
|
||||
return mm->mqd_size;
|
||||
}
|
||||
@@ -151,8 +158,8 @@ static struct kfd_mem_obj *allocate_mqd(struct mqd_manager *mm,
|
||||
if (!mqd_mem_obj)
|
||||
return NULL;
|
||||
retval = amdgpu_amdkfd_alloc_kernel_mem(node->adev,
|
||||
(ALIGN(q->ctl_stack_size, PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE)) *
|
||||
(ALIGN(ALIGN(q->ctl_stack_size, AMDGPU_GPU_PAGE_SIZE) +
|
||||
ALIGN(sizeof(struct v9_mqd), AMDGPU_GPU_PAGE_SIZE), PAGE_SIZE)) *
|
||||
NUM_XCC(node->xcc_mask),
|
||||
mqd_on_vram(node->adev) ? AMDGPU_GEM_DOMAIN_VRAM :
|
||||
AMDGPU_GEM_DOMAIN_GTT,
|
||||
@@ -360,7 +367,7 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
|
||||
struct kfd_context_save_area_header header;
|
||||
|
||||
/* Control stack is located one page after MQD. */
|
||||
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
|
||||
void *mqd_ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
@@ -397,7 +404,7 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, voi
|
||||
{
|
||||
struct v9_mqd *m;
|
||||
/* Control stack is located one page after MQD. */
|
||||
void *ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE);
|
||||
void *ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
@@ -443,7 +450,7 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd,
|
||||
*gart_addr = addr;
|
||||
|
||||
/* Control stack is located one page after MQD. */
|
||||
ctl_stack = (void *)((uintptr_t)*mqd + PAGE_SIZE);
|
||||
ctl_stack = (void *)((uintptr_t)*mqd + AMDGPU_GPU_PAGE_SIZE);
|
||||
memcpy(ctl_stack, ctl_stack_src, ctl_stack_size);
|
||||
|
||||
m->cp_hqd_pq_doorbell_control =
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
* The first chunk is the TBA used for the CWSR ISA code. The second
|
||||
* chunk is used as TMA for user-mode trap handler setup in daisy-chain mode.
|
||||
*/
|
||||
#define KFD_CWSR_TBA_TMA_SIZE (PAGE_SIZE * 2)
|
||||
#define KFD_CWSR_TMA_OFFSET (PAGE_SIZE + 2048)
|
||||
#define KFD_CWSR_TBA_TMA_SIZE (AMDGPU_GPU_PAGE_SIZE * 2)
|
||||
#define KFD_CWSR_TMA_OFFSET (AMDGPU_GPU_PAGE_SIZE + 2048)
|
||||
|
||||
#define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \
|
||||
(KFD_MAX_NUM_OF_PROCESSES * \
|
||||
|
||||
@@ -249,10 +249,10 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
|
||||
topo_dev->node_props.gfx_target_version < 90000)
|
||||
/* metadata_queue_size not supported on GFX7/GFX8 */
|
||||
expected_queue_size =
|
||||
properties->queue_size / 2;
|
||||
PAGE_ALIGN(properties->queue_size / 2);
|
||||
else
|
||||
expected_queue_size =
|
||||
properties->queue_size + properties->metadata_queue_size;
|
||||
PAGE_ALIGN(properties->queue_size + properties->metadata_queue_size);
|
||||
|
||||
vm = drm_priv_to_vm(pdd->drm_priv);
|
||||
err = amdgpu_bo_reserve(vm->root.bo, false);
|
||||
@@ -492,10 +492,11 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
|
||||
cu_num = props->simd_count / props->simd_per_cu / NUM_XCC(dev->gpu->xcc_mask);
|
||||
wave_num = get_num_waves(props, gfxv, cu_num);
|
||||
|
||||
wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props), PAGE_SIZE);
|
||||
wg_data_size = ALIGN(cu_num * WG_CONTEXT_DATA_SIZE_PER_CU(gfxv, props),
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
ctl_stack_size = wave_num * CNTL_STACK_BYTES_PER_WAVE(gfxv) + 8;
|
||||
ctl_stack_size = ALIGN(SIZEOF_HSA_USER_CONTEXT_SAVE_AREA_HEADER + ctl_stack_size,
|
||||
PAGE_SIZE);
|
||||
AMDGPU_GPU_PAGE_SIZE);
|
||||
|
||||
if ((gfxv / 10000 * 10000) == 100000) {
|
||||
/* HW design limits control stack size to 0x7000.
|
||||
@@ -507,7 +508,7 @@ void kfd_queue_ctx_save_restore_size(struct kfd_topology_device *dev)
|
||||
|
||||
props->ctl_stack_size = ctl_stack_size;
|
||||
props->debug_memory_size = ALIGN(wave_num * DEBUGGER_BYTES_PER_WAVE, DEBUGGER_BYTES_ALIGN);
|
||||
props->cwsr_size = ctl_stack_size + wg_data_size;
|
||||
props->cwsr_size = ALIGN(ctl_stack_size + wg_data_size, PAGE_SIZE);
|
||||
|
||||
if (gfxv == 80002) /* GFX_VERSION_TONGA */
|
||||
props->eop_buffer_size = 0x8000;
|
||||
|
||||
@@ -147,6 +147,7 @@ void dcn401_init_hw(struct dc *dc)
|
||||
int edp_num;
|
||||
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
|
||||
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
|
||||
bool dchub_ref_freq_changed;
|
||||
int current_dchub_ref_freq = 0;
|
||||
|
||||
if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
|
||||
@@ -360,14 +361,18 @@ void dcn401_init_hw(struct dc *dc)
|
||||
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
|
||||
dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
|
||||
dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
|
||||
|
||||
/* sw and fw FAMS versions must match for support */
|
||||
dc->debug.fams2_config.bits.enable &=
|
||||
dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
|
||||
if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
|
||||
|| res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
|
||||
dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver;
|
||||
dchub_ref_freq_changed =
|
||||
res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq;
|
||||
if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) &&
|
||||
dc->res_pool->funcs->update_bw_bounding_box &&
|
||||
dc->clk_mgr && dc->clk_mgr->bw_params) {
|
||||
/* update bounding box if FAMS2 disabled, or if dchub clk has changed */
|
||||
if (dc->clk_mgr)
|
||||
dc->res_pool->funcs->update_bw_bounding_box(dc,
|
||||
dc->clk_mgr->bw_params);
|
||||
dc->res_pool->funcs->update_bw_bounding_box(dc,
|
||||
dc->clk_mgr->bw_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "dce/dce_dmcu.h"
|
||||
#include "dce/dce_aux.h"
|
||||
#include "dce/dce_i2c.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
|
||||
#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
|
||||
#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f
|
||||
@@ -444,6 +445,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
|
||||
HUBBUB_MASK_SH_LIST_DCN10(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn10_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static int map_transmitter_id_to_phy_instance(
|
||||
enum transmitter transmitter)
|
||||
{
|
||||
@@ -917,6 +945,11 @@ static void dcn10_resource_destruct(struct dcn10_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.opps[i] != NULL)
|
||||
pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
|
||||
@@ -1653,6 +1686,14 @@ static bool dcn10_resource_construct(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn10_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!resource_construct(num_virtual_links, dc, &pool->base,
|
||||
&res_create_funcs))
|
||||
goto fail;
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
#include "dce/dce_dmcu.h"
|
||||
#include "dce/dce_aux.h"
|
||||
#include "dce/dce_i2c.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "vm_helper.h"
|
||||
|
||||
#include "link_enc_cfg.h"
|
||||
@@ -550,6 +551,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
|
||||
HUBBUB_MASK_SH_LIST_DCN20(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn20_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
#define vmid_regs(id)\
|
||||
[id] = {\
|
||||
DCN20_VMID_REG_LIST(id)\
|
||||
@@ -1104,6 +1132,12 @@ static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn20_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -2692,6 +2726,14 @@ static bool dcn20_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn20_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
|
||||
pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
|
||||
if (pool->base.dscs[i] == NULL) {
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "dce/dce_aux.h"
|
||||
#include "dce/dce_i2c.h"
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
|
||||
#include "cyan_skillfish_ip_offset.h"
|
||||
|
||||
@@ -755,6 +756,33 @@ static struct hubbub *dcn201_hubbub_create(struct dc_context *ctx)
|
||||
return &hubbub->base;
|
||||
}
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn201_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct timing_generator *dcn201_timing_generator_create(
|
||||
struct dc_context *ctx,
|
||||
uint32_t instance)
|
||||
@@ -930,6 +958,11 @@ static void dcn201_resource_destruct(struct dcn201_resource_pool *pool)
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn201_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -1276,6 +1309,14 @@ static bool dcn201_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn201_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
if (!resource_construct(num_virtual_links, dc, &pool->base,
|
||||
&res_create_funcs))
|
||||
goto create_fail;
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "dce/dce_dmcu.h"
|
||||
#include "dce/dce_aux.h"
|
||||
#include "dce/dce_i2c.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dcn21_resource.h"
|
||||
#include "vm_helper.h"
|
||||
#include "dcn20/dcn20_vmid.h"
|
||||
@@ -329,6 +330,25 @@ static const struct dcn_hubbub_mask hubbub_mask = {
|
||||
HUBBUB_MASK_SH_LIST_DCN21(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = { 0 };
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = { 0 };
|
||||
|
||||
static struct dio *dcn21_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
#define vmid_regs(id)\
|
||||
[id] = {\
|
||||
@@ -677,6 +697,12 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn20_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -1654,6 +1680,14 @@ static bool dcn21_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn21_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
|
||||
pool->base.dscs[i] = dcn21_dsc_create(ctx, i);
|
||||
if (pool->base.dscs[i] == NULL) {
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn30/dcn30_dccg.h"
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "link_service.h"
|
||||
#include "dce/dce_panel_cntl.h"
|
||||
|
||||
@@ -886,6 +887,33 @@ static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx)
|
||||
return &hubbub3->base;
|
||||
}
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn30_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct timing_generator *dcn30_timing_generator_create(
|
||||
struct dc_context *ctx,
|
||||
uint32_t instance)
|
||||
@@ -1095,6 +1123,12 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn30_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -2464,6 +2498,14 @@ static bool dcn30_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn30_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn30_hubp_create(ctx, i);
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn301/dcn301_dccg.h"
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dcn30/dcn30_dio_stream_encoder.h"
|
||||
#include "dcn301/dcn301_dio_link_encoder.h"
|
||||
#include "dcn301/dcn301_panel_cntl.h"
|
||||
@@ -843,6 +844,33 @@ static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx)
|
||||
return &hubbub3->base;
|
||||
}
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn301_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct timing_generator *dcn301_timing_generator_create(
|
||||
struct dc_context *ctx, uint32_t instance)
|
||||
{
|
||||
@@ -1066,6 +1094,12 @@ static void dcn301_destruct(struct dcn301_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn301_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -1582,6 +1616,14 @@ static bool dcn301_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn301_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "dml/dcn30/dcn30_fpu.h"
|
||||
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
|
||||
#include "link_service.h"
|
||||
|
||||
@@ -253,6 +254,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn302_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn302_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1022,6 +1050,11 @@ static void dcn302_resource_destruct(struct resource_pool *pool)
|
||||
pool->hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->dio));
|
||||
pool->dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->pipe_count; i++) {
|
||||
if (pool->dpps[i] != NULL) {
|
||||
kfree(TO_DCN20_DPP(pool->dpps[i]));
|
||||
@@ -1372,6 +1405,14 @@ static bool dcn302_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->dio = dcn302_dio_create(ctx);
|
||||
if (pool->dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->pipe_count; i++) {
|
||||
pool->hubps[i] = dcn302_hubp_create(ctx, i);
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "dml/dcn30/dcn30_fpu.h"
|
||||
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
|
||||
#include "link_service.h"
|
||||
|
||||
@@ -249,6 +250,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dio *dcn303_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -966,6 +994,11 @@ static void dcn303_resource_destruct(struct resource_pool *pool)
|
||||
pool->hubbub = NULL;
|
||||
}
|
||||
|
||||
if (pool->dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->dio));
|
||||
pool->dio = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pool->pipe_count; i++) {
|
||||
if (pool->dpps[i] != NULL) {
|
||||
kfree(TO_DCN20_DPP(pool->dpps[i]));
|
||||
@@ -1304,6 +1337,14 @@ static bool dcn303_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->dio = dcn303_dio_create(ctx);
|
||||
if (pool->dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->pipe_count; i++) {
|
||||
pool->hubps[i] = dcn303_hubp_create(ctx, i);
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "dce/dce_audio.h"
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
@@ -810,6 +811,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn31 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -1021,6 +1037,18 @@ static struct mpc *dcn31_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn31_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1396,6 +1424,10 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn31_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -2063,6 +2095,14 @@ static bool dcn31_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn31_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "dce/dce_audio.h"
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
@@ -822,6 +823,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn314 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -1079,6 +1095,18 @@ static struct mpc *dcn31_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn314_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1455,6 +1483,10 @@ static void dcn314_resource_destruct(struct dcn314_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn31_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -1987,6 +2019,14 @@ static bool dcn314_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn314_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "dce/dce_audio.h"
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
@@ -809,6 +810,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn31 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -1020,6 +1036,18 @@ static struct mpc *dcn31_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn315_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1397,6 +1425,10 @@ static void dcn315_resource_destruct(struct dcn315_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn31_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -2012,6 +2044,14 @@ static bool dcn315_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn315_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "dce/dce_audio.h"
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
@@ -804,6 +805,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_registers dio_regs = {
|
||||
DIO_REG_LIST_DCN10()
|
||||
};
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn31 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -1013,6 +1029,18 @@ static struct mpc *dcn31_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn316_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1392,6 +1420,10 @@ static void dcn316_resource_destruct(struct dcn316_resource_pool *pool)
|
||||
kfree(pool->base.hubbub);
|
||||
pool->base.hubbub = NULL;
|
||||
}
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
if (pool->base.dpps[i] != NULL)
|
||||
dcn31_dpp_destroy(&pool->base.dpps[i]);
|
||||
@@ -1887,6 +1919,14 @@ static bool dcn316_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn316_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn32/dcn32_dccg.h"
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
@@ -643,6 +644,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dcn_dio_registers dio_regs;
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn32 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -833,6 +847,22 @@ static struct clock_source *dcn32_clock_source_create(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dio *dcn32_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
#undef REG_STRUCT
|
||||
#define REG_STRUCT dio_regs
|
||||
DIO_REG_LIST_DCN10();
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1494,6 +1524,11 @@ static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
|
||||
if (pool->base.dccg != NULL)
|
||||
dcn_dccg_destroy(&pool->base.dccg);
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.oem_device != NULL) {
|
||||
struct dc *dc = pool->base.oem_device->ctx->dc;
|
||||
|
||||
@@ -2373,6 +2408,14 @@ static bool dcn32_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn32_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs, TGs, ABMs */
|
||||
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn32/dcn32_dccg.h"
|
||||
#include "dcn10/dcn10_resource.h"
|
||||
@@ -639,6 +640,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dcn_dio_registers dio_regs;
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn321 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -827,6 +841,22 @@ static struct clock_source *dcn321_clock_source_create(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dio *dcn321_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
#undef REG_STRUCT
|
||||
#define REG_STRUCT dio_regs
|
||||
DIO_REG_LIST_DCN10();
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1474,6 +1504,11 @@ static void dcn321_resource_destruct(struct dcn321_resource_pool *pool)
|
||||
if (pool->base.dccg != NULL)
|
||||
dcn_dccg_destroy(&pool->base.dccg);
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
|
||||
if (pool->base.oem_device != NULL) {
|
||||
struct dc *dc = pool->base.oem_device->ctx->dc;
|
||||
|
||||
@@ -1872,6 +1907,14 @@ static bool dcn321_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn321_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs, TGs, ABMs */
|
||||
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn35/dcn35_dccg.h"
|
||||
@@ -664,6 +665,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dcn_dio_registers dio_regs;
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn35 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -973,6 +987,22 @@ static struct mpc *dcn35_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn35_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
#undef REG_STRUCT
|
||||
#define REG_STRUCT dio_regs
|
||||
DIO_REG_LIST_DCN10();
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1563,6 +1593,11 @@ static void dcn35_resource_destruct(struct dcn35_resource_pool *pool)
|
||||
|
||||
if (pool->base.dccg != NULL)
|
||||
dcn_dccg_destroy(&pool->base.dccg);
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hubp *dcn35_hubp_create(
|
||||
@@ -2033,6 +2068,14 @@ static bool dcn35_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn35_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn35/dcn35_dccg.h"
|
||||
@@ -644,6 +645,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dcn_dio_registers dio_regs;
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn351 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -953,6 +967,22 @@ static struct mpc *dcn35_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn351_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
#undef REG_STRUCT
|
||||
#define REG_STRUCT dio_regs
|
||||
DIO_REG_LIST_DCN10();
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1543,6 +1573,11 @@ static void dcn351_resource_destruct(struct dcn351_resource_pool *pool)
|
||||
|
||||
if (pool->base.dccg != NULL)
|
||||
dcn_dccg_destroy(&pool->base.dccg);
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hubp *dcn35_hubp_create(
|
||||
@@ -2005,6 +2040,14 @@ static bool dcn351_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn351_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "dce/dce_hwseq.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dio/virtual/virtual_stream_encoder.h"
|
||||
#include "dio/dcn10/dcn10_dio.h"
|
||||
#include "dce110/dce110_resource.h"
|
||||
#include "dml/display_mode_vba.h"
|
||||
#include "dcn35/dcn35_dccg.h"
|
||||
@@ -651,6 +652,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
|
||||
DCN20_VMID_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static struct dcn_dio_registers dio_regs;
|
||||
|
||||
#define DIO_MASK_SH_LIST(mask_sh)\
|
||||
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
|
||||
|
||||
static const struct dcn_dio_shift dio_shift = {
|
||||
DIO_MASK_SH_LIST(__SHIFT)
|
||||
};
|
||||
|
||||
static const struct dcn_dio_mask dio_mask = {
|
||||
DIO_MASK_SH_LIST(_MASK)
|
||||
};
|
||||
|
||||
static const struct resource_caps res_cap_dcn36 = {
|
||||
.num_timing_generator = 4,
|
||||
.num_opp = 4,
|
||||
@@ -960,6 +974,22 @@ static struct mpc *dcn35_mpc_create(
|
||||
return &mpc30->base;
|
||||
}
|
||||
|
||||
static struct dio *dcn36_dio_create(struct dc_context *ctx)
|
||||
{
|
||||
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
|
||||
|
||||
if (!dio10)
|
||||
return NULL;
|
||||
|
||||
#undef REG_STRUCT
|
||||
#define REG_STRUCT dio_regs
|
||||
DIO_REG_LIST_DCN10();
|
||||
|
||||
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
|
||||
|
||||
return &dio10->base;
|
||||
}
|
||||
|
||||
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
@@ -1550,6 +1580,11 @@ static void dcn36_resource_destruct(struct dcn36_resource_pool *pool)
|
||||
|
||||
if (pool->base.dccg != NULL)
|
||||
dcn_dccg_destroy(&pool->base.dccg);
|
||||
|
||||
if (pool->base.dio != NULL) {
|
||||
kfree(TO_DCN10_DIO(pool->base.dio));
|
||||
pool->base.dio = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hubp *dcn35_hubp_create(
|
||||
@@ -2012,6 +2047,14 @@ static bool dcn36_resource_construct(
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* DIO */
|
||||
pool->base.dio = dcn36_dio_create(ctx);
|
||||
if (pool->base.dio == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_error("DC: failed to create dio!\n");
|
||||
goto create_fail;
|
||||
}
|
||||
|
||||
/* HUBPs, DPPs, OPPs and TGs */
|
||||
for (i = 0; i < pool->base.pipe_count; i++) {
|
||||
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);
|
||||
|
||||
@@ -262,7 +262,6 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
|
||||
"smu fw program = %d, version = 0x%08x (%d.%d.%d)\n",
|
||||
smu->smc_driver_if_version, if_version,
|
||||
smu_program, smu_version, smu_major, smu_minor, smu_debug);
|
||||
dev_info(smu->adev->dev, "SMU driver if version not matched\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -101,7 +101,6 @@ int smu_v12_0_check_fw_version(struct smu_context *smu)
|
||||
"smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
|
||||
smu->smc_driver_if_version, if_version,
|
||||
smu_program, smu_version, smu_major, smu_minor, smu_debug);
|
||||
dev_info(smu->adev->dev, "SMU driver if version not matched\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -284,7 +284,6 @@ int smu_v14_0_check_fw_version(struct smu_context *smu)
|
||||
"smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
|
||||
smu->smc_driver_if_version, if_version,
|
||||
smu_program, smu_version, smu_major, smu_minor, smu_debug);
|
||||
dev_info(adev->dev, "SMU driver if version not matched\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -436,7 +436,7 @@ static void ast_init_analog(struct ast_device *ast)
|
||||
/* Finally, clear bits [17:16] of SCU2c */
|
||||
data = ast_read32(ast, 0x1202c);
|
||||
data &= 0xfffcffff;
|
||||
ast_write32(ast, 0, data);
|
||||
ast_write32(ast, 0x1202c, data);
|
||||
|
||||
/* Disable DVO */
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);
|
||||
|
||||
@@ -1569,11 +1569,17 @@ EXPORT_SYMBOL(devm_drm_put_bridge);
|
||||
static void drm_bridge_debugfs_show_bridge(struct drm_printer *p,
|
||||
struct drm_bridge *bridge,
|
||||
unsigned int idx,
|
||||
bool lingering)
|
||||
bool lingering,
|
||||
bool scoped)
|
||||
{
|
||||
unsigned int refcount = kref_read(&bridge->refcount);
|
||||
|
||||
if (scoped)
|
||||
refcount--;
|
||||
|
||||
drm_printf(p, "bridge[%u]: %ps\n", idx, bridge->funcs);
|
||||
|
||||
drm_printf(p, "\trefcount: %u%s\n", kref_read(&bridge->refcount),
|
||||
drm_printf(p, "\trefcount: %u%s\n", refcount,
|
||||
lingering ? " [lingering]" : "");
|
||||
|
||||
drm_printf(p, "\ttype: [%d] %s\n",
|
||||
@@ -1607,10 +1613,10 @@ static int allbridges_show(struct seq_file *m, void *data)
|
||||
mutex_lock(&bridge_lock);
|
||||
|
||||
list_for_each_entry(bridge, &bridge_list, list)
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, false);
|
||||
|
||||
list_for_each_entry(bridge, &bridge_lingering_list, list)
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true);
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true, false);
|
||||
|
||||
mutex_unlock(&bridge_lock);
|
||||
|
||||
@@ -1625,7 +1631,7 @@ static int encoder_bridges_show(struct seq_file *m, void *data)
|
||||
unsigned int idx = 0;
|
||||
|
||||
drm_for_each_bridge_in_chain_scoped(encoder, bridge)
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
|
||||
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,6 @@ static void drm_events_release(struct drm_file *file_priv)
|
||||
void drm_file_free(struct drm_file *file)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int idx;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
@@ -250,11 +249,9 @@ void drm_file_free(struct drm_file *file)
|
||||
|
||||
drm_events_release(file);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET) &&
|
||||
drm_dev_enter(dev, &idx)) {
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
drm_fb_release(file);
|
||||
drm_property_destroy_user_blobs(dev, file);
|
||||
drm_dev_exit(idx);
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#include <linux/compat.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
@@ -374,6 +375,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
if (nr >= ARRAY_SIZE(drm_compat_ioctls))
|
||||
return drm_ioctl(filp, cmd, arg);
|
||||
|
||||
nr = array_index_nospec(nr, ARRAY_SIZE(drm_compat_ioctls));
|
||||
fn = drm_compat_ioctls[nr].fn;
|
||||
if (!fn)
|
||||
return drm_ioctl(filp, cmd, arg);
|
||||
|
||||
@@ -577,13 +577,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
|
||||
*/
|
||||
WARN_ON(!list_empty(&dev->mode_config.fb_list));
|
||||
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
|
||||
if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
|
||||
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
|
||||
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
|
||||
|
||||
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
|
||||
drm_framebuffer_print_info(&p, 1, fb);
|
||||
}
|
||||
list_del_init(&fb->filp_head);
|
||||
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
|
||||
drm_framebuffer_print_info(&p, 1, fb);
|
||||
drm_framebuffer_free(&fb->base.refcount);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
|
||||
intel_dp->DP |= DP_SYNC_VS_HIGH;
|
||||
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
|
||||
|
||||
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
|
||||
if (pipe_config->enhanced_framing)
|
||||
intel_dp->DP |= DP_ENHANCED_FRAMING;
|
||||
|
||||
intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
|
||||
|
||||
@@ -889,7 +889,7 @@ gen11_dsi_set_transcoder_timings(struct intel_encoder *encoder,
|
||||
* non-compressed link speeds, and simplifies down to the ratio between
|
||||
* compressed and non-compressed bpp.
|
||||
*/
|
||||
if (crtc_state->dsc.compression_enable) {
|
||||
if (is_vid_mode(intel_dsi) && crtc_state->dsc.compression_enable) {
|
||||
mul = fxp_q4_to_int(crtc_state->dsc.compressed_bpp_x16);
|
||||
div = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
|
||||
}
|
||||
@@ -1503,7 +1503,7 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
|
||||
struct drm_display_mode *adjusted_mode =
|
||||
&pipe_config->hw.adjusted_mode;
|
||||
|
||||
if (pipe_config->dsc.compressed_bpp_x16) {
|
||||
if (is_vid_mode(intel_dsi) && pipe_config->dsc.compressed_bpp_x16) {
|
||||
int div = fxp_q4_to_int(pipe_config->dsc.compressed_bpp_x16);
|
||||
int mul = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
|
||||
|
||||
|
||||
@@ -2971,6 +2971,53 @@ static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_cdclk_update_crtc_min_voltage_level(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
u8 old_min_voltage_level,
|
||||
u8 new_min_voltage_level,
|
||||
bool *need_cdclk_calc)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(state);
|
||||
struct intel_cdclk_state *cdclk_state;
|
||||
bool allow_voltage_level_decrease = intel_any_crtc_needs_modeset(state);
|
||||
int ret;
|
||||
|
||||
if (new_min_voltage_level == old_min_voltage_level)
|
||||
return 0;
|
||||
|
||||
if (!allow_voltage_level_decrease &&
|
||||
new_min_voltage_level < old_min_voltage_level)
|
||||
return 0;
|
||||
|
||||
cdclk_state = intel_atomic_get_cdclk_state(state);
|
||||
if (IS_ERR(cdclk_state))
|
||||
return PTR_ERR(cdclk_state);
|
||||
|
||||
old_min_voltage_level = cdclk_state->min_voltage_level[crtc->pipe];
|
||||
|
||||
if (new_min_voltage_level == old_min_voltage_level)
|
||||
return 0;
|
||||
|
||||
if (!allow_voltage_level_decrease &&
|
||||
new_min_voltage_level < old_min_voltage_level)
|
||||
return 0;
|
||||
|
||||
cdclk_state->min_voltage_level[crtc->pipe] = new_min_voltage_level;
|
||||
|
||||
ret = intel_atomic_lock_global_state(&cdclk_state->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*need_cdclk_calc = true;
|
||||
|
||||
drm_dbg_kms(display->drm,
|
||||
"[CRTC:%d:%s] min voltage level: %d -> %d\n",
|
||||
crtc->base.base.id, crtc->base.name,
|
||||
old_min_voltage_level, new_min_voltage_level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state,
|
||||
int old_min_cdclk, int new_min_cdclk,
|
||||
bool *need_cdclk_calc)
|
||||
@@ -3386,6 +3433,13 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state,
|
||||
need_cdclk_calc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_cdclk_update_crtc_min_voltage_level(state, crtc,
|
||||
old_crtc_state->min_voltage_level,
|
||||
new_crtc_state->min_voltage_level,
|
||||
need_cdclk_calc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -151,7 +151,6 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
|
||||
struct drm_sysfb_device *sysfb;
|
||||
struct drm_device *dev;
|
||||
struct resource *mem = NULL;
|
||||
void __iomem *screen_base = NULL;
|
||||
struct drm_plane *primary_plane;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
@@ -238,21 +237,38 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
|
||||
|
||||
mem_flags = efidrm_get_mem_flags(dev, res->start, vsize);
|
||||
|
||||
if (mem_flags & EFI_MEMORY_WC)
|
||||
screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
|
||||
else if (mem_flags & EFI_MEMORY_UC)
|
||||
screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
|
||||
else if (mem_flags & EFI_MEMORY_WT)
|
||||
screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
|
||||
MEMREMAP_WT);
|
||||
else if (mem_flags & EFI_MEMORY_WB)
|
||||
screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
|
||||
MEMREMAP_WB);
|
||||
else
|
||||
if (mem_flags & EFI_MEMORY_WC) {
|
||||
void __iomem *screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
|
||||
resource_size(mem));
|
||||
|
||||
if (!screen_base)
|
||||
return ERR_PTR(-ENXIO);
|
||||
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
|
||||
} else if (mem_flags & EFI_MEMORY_UC) {
|
||||
void __iomem *screen_base = devm_ioremap(&pdev->dev, mem->start,
|
||||
resource_size(mem));
|
||||
|
||||
if (!screen_base)
|
||||
return ERR_PTR(-ENXIO);
|
||||
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
|
||||
} else if (mem_flags & EFI_MEMORY_WT) {
|
||||
void *screen_base = devm_memremap(&pdev->dev, mem->start,
|
||||
resource_size(mem), MEMREMAP_WT);
|
||||
|
||||
if (IS_ERR(screen_base))
|
||||
return ERR_CAST(screen_base);
|
||||
iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
|
||||
} else if (mem_flags & EFI_MEMORY_WB) {
|
||||
void *screen_base = devm_memremap(&pdev->dev, mem->start,
|
||||
resource_size(mem), MEMREMAP_WB);
|
||||
|
||||
if (IS_ERR(screen_base))
|
||||
return ERR_CAST(screen_base);
|
||||
iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
|
||||
} else {
|
||||
drm_err(dev, "invalid mem_flags: 0x%llx\n", mem_flags);
|
||||
if (!screen_base)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Modesetting
|
||||
|
||||
@@ -837,6 +837,14 @@ static void detect_preproduction_hw(struct xe_device *xe)
|
||||
}
|
||||
}
|
||||
|
||||
static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
|
||||
{
|
||||
struct xe_device *xe = arg;
|
||||
|
||||
if (atomic_read(&xe->wedged.flag))
|
||||
xe_pm_runtime_put(xe);
|
||||
}
|
||||
|
||||
int xe_device_probe(struct xe_device *xe)
|
||||
{
|
||||
struct xe_tile *tile;
|
||||
@@ -1013,6 +1021,10 @@ int xe_device_probe(struct xe_device *xe)
|
||||
|
||||
detect_preproduction_hw(xe);
|
||||
|
||||
err = drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe);
|
||||
if (err)
|
||||
goto err_unregister_display;
|
||||
|
||||
return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
|
||||
|
||||
err_unregister_display:
|
||||
@@ -1216,13 +1228,6 @@ u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address)
|
||||
return address & GENMASK_ULL(xe->info.va_bits - 1, 0);
|
||||
}
|
||||
|
||||
static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
|
||||
{
|
||||
struct xe_device *xe = arg;
|
||||
|
||||
xe_pm_runtime_put(xe);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: Xe Device Wedging
|
||||
*
|
||||
@@ -1300,15 +1305,9 @@ void xe_device_declare_wedged(struct xe_device *xe)
|
||||
return;
|
||||
}
|
||||
|
||||
xe_pm_runtime_get_noresume(xe);
|
||||
|
||||
if (drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe)) {
|
||||
drm_err(&xe->drm, "Failed to register xe_device_wedged_fini clean-up. Although device is wedged.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!atomic_xchg(&xe->wedged.flag, 1)) {
|
||||
xe->needs_flr_on_fini = true;
|
||||
xe_pm_runtime_get_noresume(xe);
|
||||
drm_err(&xe->drm,
|
||||
"CRITICAL: Xe has declared device %s as wedged.\n"
|
||||
"IOCTLs and executions are blocked. Only a rebind may clear the failure\n"
|
||||
|
||||
@@ -187,6 +187,12 @@ static int xe_pagefault_service(struct xe_pagefault *pf)
|
||||
goto unlock_vm;
|
||||
}
|
||||
|
||||
if (xe_vma_read_only(vma) &&
|
||||
pf->consumer.access_type != XE_PAGEFAULT_ACCESS_TYPE_READ) {
|
||||
err = -EPERM;
|
||||
goto unlock_vm;
|
||||
}
|
||||
|
||||
atomic = xe_pagefault_access_is_atomic(pf->consumer.access_type);
|
||||
|
||||
if (xe_vma_is_cpu_addr_mirror(vma))
|
||||
|
||||
@@ -380,6 +380,18 @@ int xe_pxp_init(struct xe_device *xe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On PTL, older GSC FWs have a bug that can cause them to crash during
|
||||
* PXP invalidation events, which leads to a complete loss of power
|
||||
* management on the media GT. Therefore, we can't use PXP on FWs that
|
||||
* have this bug, which was fixed in PTL GSC build 1396.
|
||||
*/
|
||||
if (xe->info.platform == XE_PANTHERLAKE &&
|
||||
gt->uc.gsc.fw.versions.found[XE_UC_FW_VER_RELEASE].build < 1396) {
|
||||
drm_info(&xe->drm, "PXP requires PTL GSC build 1396 or newer\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL);
|
||||
if (!pxp) {
|
||||
err = -ENOMEM;
|
||||
@@ -512,7 +524,7 @@ static int __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q)
|
||||
static int pxp_start(struct xe_pxp *pxp, u8 type)
|
||||
{
|
||||
int ret = 0;
|
||||
bool restart = false;
|
||||
bool restart;
|
||||
|
||||
if (!xe_pxp_is_enabled(pxp))
|
||||
return -ENODEV;
|
||||
@@ -541,6 +553,8 @@ wait_for_idle:
|
||||
msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS)))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
restart = false;
|
||||
|
||||
mutex_lock(&pxp->mutex);
|
||||
|
||||
/* If PXP is not already active, turn it on */
|
||||
@@ -583,6 +597,7 @@ wait_for_idle:
|
||||
drm_err(&pxp->xe->drm, "PXP termination failed before start\n");
|
||||
mutex_lock(&pxp->mutex);
|
||||
pxp->status = XE_PXP_ERROR;
|
||||
complete_all(&pxp->termination);
|
||||
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -870,11 +885,6 @@ wait_for_activation:
|
||||
pxp->key_instance++;
|
||||
needs_queue_inval = true;
|
||||
break;
|
||||
default:
|
||||
drm_err(&pxp->xe->drm, "unexpected state during PXP suspend: %u",
|
||||
pxp->status);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -899,7 +909,6 @@ wait_for_activation:
|
||||
|
||||
pxp->last_suspend_key_instance = pxp->key_instance;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -903,7 +903,7 @@ int xe_svm_init(struct xe_vm *vm)
|
||||
void xe_svm_close(struct xe_vm *vm)
|
||||
{
|
||||
xe_assert(vm->xe, xe_vm_is_closed(vm));
|
||||
flush_work(&vm->svm.garbage_collector.work);
|
||||
disable_work_sync(&vm->svm.garbage_collector.work);
|
||||
xe_svm_put_pagemaps(vm);
|
||||
drm_pagemap_release_owner(&vm->svm.peer);
|
||||
}
|
||||
|
||||
@@ -408,8 +408,15 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
||||
struct xe_device *xe = to_xe_device(dev);
|
||||
struct xe_file *xef = to_xe_file(file);
|
||||
struct drm_xe_madvise *args = data;
|
||||
struct xe_vmas_in_madvise_range madvise_range = {.addr = args->start,
|
||||
.range = args->range, };
|
||||
struct xe_vmas_in_madvise_range madvise_range = {
|
||||
/*
|
||||
* Userspace may pass canonical (sign-extended) addresses.
|
||||
* Strip the sign extension to get the internal non-canonical
|
||||
* form used by the GPUVM, matching xe_vm_bind_ioctl() behavior.
|
||||
*/
|
||||
.addr = xe_device_uncanonicalize_addr(xe, args->start),
|
||||
.range = args->range,
|
||||
};
|
||||
struct xe_madvise_details details;
|
||||
struct xe_vm *vm;
|
||||
struct drm_exec exec;
|
||||
@@ -439,7 +446,7 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
||||
if (err)
|
||||
goto unlock_vm;
|
||||
|
||||
err = xe_vm_alloc_madvise_vma(vm, args->start, args->range);
|
||||
err = xe_vm_alloc_madvise_vma(vm, madvise_range.addr, args->range);
|
||||
if (err)
|
||||
goto madv_fini;
|
||||
|
||||
@@ -482,7 +489,8 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
|
||||
madvise_funcs[attr_type](xe, vm, madvise_range.vmas, madvise_range.num_vmas, args,
|
||||
&details);
|
||||
|
||||
err = xe_vm_invalidate_madvise_range(vm, args->start, args->start + args->range);
|
||||
err = xe_vm_invalidate_madvise_range(vm, madvise_range.addr,
|
||||
madvise_range.addr + args->range);
|
||||
|
||||
if (madvise_range.has_svm_userptr_vmas)
|
||||
xe_svm_notifier_unlock(vm);
|
||||
|
||||
Reference in new issue
Block a user