diff options
author | Joel Stanley <joel@jms.id.au> | 2021-07-26 04:23:00 +0300 |
---|---|---|
committer | Joel Stanley <joel@jms.id.au> | 2021-07-26 04:23:08 +0300 |
commit | 1519240139a91e3dbc97d8f79de29a22a3328257 (patch) | |
tree | 2c5546c766701be6a6c278989c6b28dadb61a0b6 /drivers/gpu | |
parent | 1cd5242658fca83f394b08e950768845a20a8b16 (diff) | |
parent | 71046eac2db9aeccf10763d034a1a123911c9a81 (diff) | |
download | linux-1519240139a91e3dbc97d8f79de29a22a3328257.tar.xz |
Merge tag 'v5.10.53' into dev-5.10
This is the 5.10.53 stable release
Signed-off-by: Joel Stanley <joel@jms.id.au>
Diffstat (limited to 'drivers/gpu')
56 files changed, 486 insertions, 276 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5da487b64a66..26f8a2138377 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -48,12 +48,6 @@ static struct { spinlock_t mem_limit_lock; } kfd_mem_limit; -/* Struct used for amdgpu_amdkfd_bo_validate */ -struct amdgpu_vm_parser { - uint32_t domain; - bool wait; -}; - static const char * const domain_bit_to_string[] = { "CPU", "GTT", @@ -337,11 +331,9 @@ validate_fail: return ret; } -static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo) +static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo) { - struct amdgpu_vm_parser *p = param; - - return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait); + return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false); } /* vm_validate_pt_pd_bos - Validate page table and directory BOs @@ -355,20 +347,15 @@ static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) { struct amdgpu_bo *pd = vm->root.base.bo; struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); - struct amdgpu_vm_parser param; int ret; - param.domain = AMDGPU_GEM_DOMAIN_VRAM; - param.wait = false; - - ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate, - ¶m); + ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL); if (ret) { pr_err("failed to validate PT BOs\n"); return ret; } - ret = amdgpu_amdkfd_validate(¶m, pd); + ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd); if (ret) { pr_err("failed to validate PD\n"); return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 87c7c45f1bb7..6948ab3c0d99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2760,7 +2760,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; - for (i = 0; i < ARRAY_SIZE(ip_order); i++) { + for (i = 0; i < adev->num_ip_blocks; i++) { int j; struct amdgpu_ip_block *block; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 28f20f0b722f..163188ce02bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -128,7 +128,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, struct amdgpu_device *adev = ring->adev; struct amdgpu_ib *ib = &ibs[0]; struct dma_fence *tmp = NULL; - bool skip_preamble, need_ctx_switch; + bool need_ctx_switch; unsigned patch_offset = ~0; struct amdgpu_vm *vm; uint64_t fence_ctx; @@ -221,7 +221,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (need_ctx_switch) status |= AMDGPU_HAVE_CTX_SWITCH; - skip_preamble = ring->current_ctx == fence_ctx; if (job && ring->funcs->emit_cntxcntl) { status |= job->preamble_status; status |= job->preemption_status; @@ -239,14 +238,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; - /* drop preamble IBs if we don't have a context switch */ - if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - skip_preamble && - !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) && - !amdgpu_mcbp && - !amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */ - continue; - if (job && ring->funcs->emit_frame_cntl) { if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) { amdgpu_ring_emit_frame_cntl(ring, false, secure); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 183814493658..bda4438c3925 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -22,6 +22,11 @@ #define __AMDGPU_UMC_H__ /* + * (addr / 256) * 4096, the higher 26 bits in ErrorAddr + * is the index of 4KB block + */ +#define ADDR_OF_4KB_BLOCK(addr) (((addr) & ~0xffULL) << 4) +/* * (addr / 256) * 8192, the higher 26 bits in ErrorAddr * is the index of 8KB block */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index e82f49f62f6e..1f2e2460e121 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -143,7 +143,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; @@ -269,7 +269,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003fff07, 0x40000051), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe) }; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index 5665c77a9d58..afbbe9f05d5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -233,7 +233,7 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, err_addr &= ~((0x1ULL << lsb) - 1); /* translate umc channel address to soc pa, 3 parts are included */ - retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + retired_page = ADDR_OF_4KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 6ea8a4b6efde..352a32dc609b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -486,9 +486,6 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, if (retval == -ETIME) qpd->reset_wavefronts = true; - - mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); - list_del(&q->list); if (list_empty(&qpd->queues_list)) { if (qpd->reset_wavefronts) { @@ -523,6 +520,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, int retval; uint64_t sdma_val = 0; struct kfd_process_device *pdd = qpd_to_pdd(qpd); + struct mqd_manager *mqd_mgr = + dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)]; /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || @@ -540,6 +539,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, pdd->sdma_past_activity_counter += sdma_val; dqm_unlock(dqm); + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + return retval; } @@ -1632,7 +1633,7 @@ static int set_trap_handler(struct device_queue_manager *dqm, static int process_termination_nocpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct queue *q, *next; + struct queue *q; struct device_process_node *cur, *next_dpn; int retval = 0; bool found = false; @@ -1640,12 +1641,19 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, dqm_lock(dqm); /* Clear all user mode queues */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + struct mqd_manager *mqd_mgr; int ret; + q = list_first_entry(&qpd->queues_list, struct queue, list); + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( + q->properties.type)]; ret = destroy_queue_nocpsch_locked(dqm, qpd, q); if (ret) retval = ret; + dqm_unlock(dqm); + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); } /* Unregister process */ @@ -1677,36 +1685,34 @@ static int get_wave_state(struct device_queue_manager *dqm, u32 *save_area_used_size) { struct mqd_manager *mqd_mgr; - int r; dqm_lock(dqm); - if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || - q->properties.is_active || !q->device->cwsr_enabled) { - r = -EINVAL; - goto dqm_unlock; - } - mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; - if (!mqd_mgr->get_wave_state) { - r = -EINVAL; - goto dqm_unlock; + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || + q->properties.is_active || !q->device->cwsr_enabled || + !mqd_mgr->get_wave_state) { + dqm_unlock(dqm); + return -EINVAL; } - r = mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, - ctl_stack_used_size, save_area_used_size); - -dqm_unlock: dqm_unlock(dqm); - return r; + + /* + * get_wave_state is outside the dqm lock to prevent circular locking + * and the queue should be protected against destruction by the process + * lock. + */ + return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, + ctl_stack_used_size, save_area_used_size); } static int process_termination_cpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { int retval; - struct queue *q, *next; + struct queue *q; struct kernel_queue *kq, *kq_next; struct mqd_manager *mqd_mgr; struct device_process_node *cur, *next_dpn; @@ -1763,24 +1769,26 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, qpd->reset_wavefronts = false; } - dqm_unlock(dqm); - - /* Outside the DQM lock because under the DQM lock we can't do - * reclaim or take other locks that others hold while reclaiming. - */ - if (found) - kfd_dec_compute_active(dqm->dev); - /* Lastly, free mqd resources. * Do free_mqd() after dqm_unlock to avoid circular locking. */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + q = list_first_entry(&qpd->queues_list, struct queue, list); mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)]; list_del(&q->list); qpd->queue_count--; + dqm_unlock(dqm); mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); } + dqm_unlock(dqm); + + /* Outside the DQM lock because under the DQM lock we can't do + * reclaim or take other locks that others hold while reclaiming. + */ + if (found) + kfd_dec_compute_active(dqm->dev); return retval; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 65803e153a22..d243e60c6eef 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -452,13 +452,9 @@ static const struct sysfs_ops procfs_stats_ops = { .show = kfd_procfs_stats_show, }; -static struct attribute *procfs_stats_attrs[] = { - NULL -}; - static struct kobj_type procfs_stats_type = { .sysfs_ops = &procfs_stats_ops, - .default_attrs = procfs_stats_attrs, + .release = kfd_procfs_kobj_release, }; int kfd_procfs_add_queue(struct queue *q) @@ -973,9 +969,11 @@ static void kfd_process_wq_release(struct work_struct *work) list_for_each_entry(pdd, &p->per_device_data, per_device_list) { sysfs_remove_file(p->kobj, &pdd->attr_vram); sysfs_remove_file(p->kobj, &pdd->attr_sdma); - sysfs_remove_file(p->kobj, &pdd->attr_evict); - if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) - sysfs_remove_file(p->kobj, &pdd->attr_cu_occupancy); + + sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict); + if (pdd->dev->kfd2kgd->get_cu_occupancy) + sysfs_remove_file(pdd->kobj_stats, + &pdd->attr_cu_occupancy); kobject_del(pdd->kobj_stats); kobject_put(pdd->kobj_stats); pdd->kobj_stats = NULL; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index eb1635ac8988..43c07ac2c6fc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -153,6 +153,7 @@ void pqm_uninit(struct process_queue_manager *pqm) if (pqn->q && pqn->q->gws) amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, pqn->q->gws); + kfd_procfs_del_queue(pqn->q); uninit_queue(pqn->q); list_del(&pqn->process_queue_list); kfree(pqn); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index df26c07cb912..6eb308670f48 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3702,6 +3702,23 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state, scaling_info->src_rect.y != 0)) return -EINVAL; + /* + * For reasons we don't (yet) fully understand a non-zero + * src_y coordinate into an NV12 buffer can cause a + * system hang. To avoid hangs (and maybe be overly cautious) + * let's reject both non-zero src_x and src_y. + * + * We currently know of only one use-case to reproduce a + * scenario with non-zero src_x and src_y for NV12, which + * is to gesture the YouTube Android app into full screen + * on ChromeOS. + */ + if (state->fb && + state->fb->format->format == DRM_FORMAT_NV12 && + (scaling_info->src_rect.x != 0 || + scaling_info->src_rect.y != 0)) + return -EINVAL; + scaling_info->src_rect.width = state->src_w >> 16; if (scaling_info->src_rect.width == 0) return -EINVAL; @@ -8291,7 +8308,8 @@ skip_modeset: BUG_ON(dm_new_crtc_state->stream == NULL); /* Scaling or underscan settings */ - if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state)) + if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) || + drm_atomic_crtc_needs_modeset(new_crtc_state)) update_stream_scaling_settings( &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream); @@ -8744,6 +8762,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled) continue; + ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); + if (ret) + goto fail; + if (!new_crtc_state->enable) continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1df7f1b18049..6c7235bb2f41 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -498,6 +498,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 void amdgpu_dm_init_color_mod(void); +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 5df05f0d18bc..179ff4b42f20 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -285,6 +285,37 @@ static int __set_input_tf(struct dc_transfer_func *func, } /** + * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of + * the expected size. + * Returns 0 on success. + */ +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) +{ + const struct drm_color_lut *lut = NULL; + uint32_t size = 0; + + lut = __extract_blob_lut(crtc_state->degamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Degamma LUT size. Should be %u but got %u.\n", + MAX_COLOR_LUT_ENTRIES, size); + return -EINVAL; + } + + lut = __extract_blob_lut(crtc_state->gamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES && + size != MAX_COLOR_LEGACY_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, + size); + return -EINVAL; + } + + return 0; +} + +/** * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. * @crtc: amdgpu_dm crtc state * @@ -317,14 +348,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) bool is_legacy; int r; - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); - if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) - return -EINVAL; + r = amdgpu_dm_verify_lut_sizes(&crtc->base); + if (r) + return r; + degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); - if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES && - regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES) - return -EINVAL; has_degamma = degamma_lut && !__is_lut_linear(degamma_lut, degamma_size); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 32b73ea86673..a7f8caf1086b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1704,6 +1704,8 @@ static void set_dp_mst_mode(struct dc_link *link, bool mst_enable) link->type = dc_connection_single; link->local_sink = link->remote_sinks[0]; link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT; + dc_sink_retain(link->local_sink); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); } else if (mst_enable == true && link->type == dc_connection_single && link->remote_sinks[0] != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index fce37c527a0b..8bb5912d837d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -482,10 +482,13 @@ static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *d int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert); int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c); - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - if (dpp->base.ctx->dc->debug.use_max_lb) - return mem_cfg; + if (dpp->base.ctx->dc->debug.use_max_lb) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) + return LB_MEMORY_CONFIG_3; + return LB_MEMORY_CONFIG_0; + } dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index f1e9b3b06b92..9d3ccdd35582 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -243,7 +243,7 @@ void dcn20_dccg_init(struct dce_hwseq *hws) REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0); /* This value is dependent on the hardware pipeline delay so set once per SOC */ - REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c); + REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c); } void dcn20_disable_vga( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 9e0ae18e71fa..2663f1b31842 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -64,6 +64,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff #define DCN30_MAX_DSC_IMAGE_WIDTH 5184 +#define DCN30_MAX_FMT_420_BUFFER_WIDTH 4096 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -2052,7 +2053,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->DISPCLKWithoutRamping, v->DISPCLKDPPCLKVCOSpeed); v->MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( - v->soc.clock_limits[mode_lib->soc.num_states].dispclk_mhz, + v->soc.clock_limits[mode_lib->soc.num_states - 1].dispclk_mhz, v->DISPCLKDPPCLKVCOSpeed); if (v->DISPCLKWithoutRampingRoundedToDFSGranularity > v->MaxDispclkRoundedToDFSGranularity) { @@ -3957,20 +3958,20 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1.0 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1.0 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } @@ -3987,19 +3988,30 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; - } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { - v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; - v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; - /*420 format workaround*/ - if (v->HActive[k] > 4096 && v->OutputFormat[k] == dm_420) { + } + if (v->DSCEnabled[k] && v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_DSC_IMAGE_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } + } + if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN30_MAX_FMT_420_BUFFER_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_FMT_420_BUFFER_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } } - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { v->MPCCombine[i][j][k] = false; v->NoOfDPP[i][j][k] = 4; @@ -4281,42 +4293,8 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; i++) { - v->DSCCLKRequiredMoreThanSupported[i] = false; - for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { - if (v->BlendingAndTiming[k] == k) { - if (v->Output[k] == dm_dp || v->Output[k] == dm_edp) { - if (v->OutputFormat[k] == dm_420) { - v->DSCFormatFactor = 2; - } else if (v->OutputFormat[k] == dm_444) { - v->DSCFormatFactor = 1; - } else if (v->OutputFormat[k] == dm_n422) { - v->DSCFormatFactor = 2; - } else { - v->DSCFormatFactor = 1; - } - if (v->RequiresDSC[i][k] == true) { - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { - if (v->PixelClockBackEnd[k] / 12.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) { - if (v->PixelClockBackEnd[k] / 6.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else { - if (v->PixelClockBackEnd[k] / 3.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } - } - } - } - } - } + /* Skip dscclk validation: as long as dispclk is supported, dscclk is also implicitly supported */ + for (i = 0; i < v->soc.num_states; i++) { v->NotEnoughDSCUnits[i] = false; v->TotalDSCUnitsRequired = 0.0; @@ -5319,7 +5297,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (j = 0; j < 2; j++) { if (v->ScaleRatioAndTapsSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 && v->ViewportSizeSupport[i][j] == 1 && v->DIOSupport[i] == 1 && v->ODMCombine4To1SupportCheckOK[i] == 1 - && v->NotEnoughDSCUnits[i] == 0 && v->DSCCLKRequiredMoreThanSupported[i] == 0 + && v->NotEnoughDSCUnits[i] == 0 && v->DTBCLKRequiredMoreThanSupported[i] == 0 && v->ROBSupport[i][j] == 1 && v->DISPCLK_DPPCLK_Support[i][j] == 1 && v->TotalAvailablePipesSupport[i][j] == 1 && EnoughWritebackUnits == 1 && WritebackModeSupport == 1 diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index d0ccd81ad5b4..ad3e5621a174 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -163,7 +163,7 @@ enum irq_type }; #define DAL_VALID_IRQ_SRC_NUM(src) \ - ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) + ((src) < DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) /* Number of Page Flip IRQ Sources. */ #define DAL_PFLIP_IRQ_SRC_NUM \ diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 20e554e771d1..fa8aeec304ef 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -260,7 +260,6 @@ enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, struct mod_hdcp_output output; enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; - memset(hdcp, 0, sizeof(struct mod_hdcp)); memset(&output, 0, sizeof(output)); hdcp->config = *config; HDCP_TOP_INTERFACE_TRACE(hdcp); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index f244b72e74e0..53eab2b8e2c8 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -29,8 +29,10 @@ static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) { uint64_t n = 0; uint8_t count = 0; + u8 bksv[sizeof(n)] = { }; - memcpy(&n, hdcp->auth.msg.hdcp1.bksv, sizeof(uint64_t)); + memcpy(bksv, hdcp->auth.msg.hdcp1.bksv, sizeof(hdcp->auth.msg.hdcp1.bksv)); + n = *(uint64_t *)bksv; while (n) { count++; diff --git a/drivers/gpu/drm/amd/include/navi10_enum.h b/drivers/gpu/drm/amd/include/navi10_enum.h index d5ead9680c6e..84bcb96f76ea 100644 --- a/drivers/gpu/drm/amd/include/navi10_enum.h +++ b/drivers/gpu/drm/amd/include/navi10_enum.h @@ -430,7 +430,7 @@ ARRAY_2D_DEPTH = 0x00000001, */ typedef enum ENUM_NUM_SIMD_PER_CU { -NUM_SIMD_PER_CU = 0x00000004, +NUM_SIMD_PER_CU = 0x00000002, } ENUM_NUM_SIMD_PER_CU; /* diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 351a85088d0e..f1e8bc39b16d 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -922,6 +922,11 @@ static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = { .atomic_disable = malidp_de_plane_disable, }; +static const uint64_t linear_only_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + int malidp_de_planes_init(struct drm_device *drm) { struct malidp_drm *malidp = drm->dev_private; @@ -985,8 +990,8 @@ int malidp_de_planes_init(struct drm_device *drm) */ ret = drm_universal_plane_init(drm, &plane->base, crtcs, &malidp_de_plane_funcs, formats, n, - (id == DE_SMART) ? NULL : modifiers, plane_type, - NULL); + (id == DE_SMART) ? linear_only_modifiers : modifiers, + plane_type, NULL); if (ret < 0) goto cleanup; diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 88121c0e0d05..cd93c44f2662 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) u32 i, data; u32 boot_address; + if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (data) { boot_address = get_fw_base(ast); @@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev) u8 *fw_addr = NULL; u8 jreg; + if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (!data) { @@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); u32 boot_address, offset, data; u8 linkcap[4], linkrate, linklanes, maxclk = 0xff; + u32 *plinkcap; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) /* version: 1x */ - return maxclk; - - /* Read Link Capability */ - offset = 0xf014; - *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); - if (linkcap[2] == 0) { - linkrate = linkcap[0]; - linklanes = linkcap[1]; - data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); - if (data > 0xff) - data = 0xff; - maxclk = (u8)data; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = ast_mindwm(ast, boot_address + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } + } else { + if (!ast->dp501_fw_buf) + return AST_DP501_DEFAULT_DCLK; /* 1024x768 as default */ + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = readl(ast->dp501_fw_buf + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } } return maxclk; } @@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) { struct ast_private *ast = to_ast_private(dev); u32 i, boot_address, offset, data; + u32 *pEDIDidx; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) - return false; - - /* validate PnP Monitor */ - offset = 0xf010; - data = ast_mindwm(ast, boot_address + offset); - if (!(data & 0x01)) - return false; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); - /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i += 4) { - data = ast_mindwm(ast, boot_address + offset + i); - *(u32 *)(ediddata + i) = data; + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = ast_mindwm(ast, boot_address + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = ast_mindwm(ast, boot_address + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } + } else { + if (!ast->dp501_fw_buf) + return false; + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = readl(ast->dp501_fw_buf + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = readl(ast->dp501_fw_buf + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } } return true; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 467049ca8430..b68b1ddfecb7 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -120,6 +120,7 @@ struct ast_private { void __iomem *regs; void __iomem *ioregs; + void __iomem *dp501_fw_buf; enum ast_chip chip; bool vga2_clone; @@ -298,6 +299,17 @@ int ast_mode_config_init(struct ast_private *ast); #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) +#define AST_DP501_FW_VERSION_MASK GENMASK(7, 4) +#define AST_DP501_FW_VERSION_1 BIT(4) +#define AST_DP501_PNP_CONNECTED BIT(1) + +#define AST_DP501_DEFAULT_DCLK 65 + +#define AST_DP501_GBL_VERSION 0xf000 +#define AST_DP501_PNPMONITOR 0xf010 +#define AST_DP501_LINKRATE 0xf014 +#define AST_DP501_EDID_DATA 0xf020 + int ast_mm_init(struct ast_private *ast); /* ast post */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index ee82b2ddf932..0d163511564e 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -98,7 +98,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { /* Double check it's actually working */ data = ast_read32(ast, 0xf004); - if (data != 0xFFFFFFFF) { + if ((data != 0xFFFFFFFF) && (data != 0x00)) { /* P2A works, grab silicon revision */ ast->config_mode = ast_use_p2a; @@ -446,6 +446,14 @@ struct ast_private *ast_device_create(struct drm_driver *drv, if (ret) return ERR_PTR(ret); + /* map reserved buffer */ + ast->dp501_fw_buf = NULL; + if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) { + ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0); + if (!ast->dp501_fw_buf) + drm_info(dev, "failed to map reserved buffer!\n"); + } + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index d0c65610ebb5..f56ff97c9899 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2369,9 +2369,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev) clk_prepare_enable(clk); pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync failed\n"); + dev_err(dev, "pm_runtime_resume_and_get failed\n"); pm_runtime_disable(dev); goto clk_disable; } diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c index 76373e31df92..b31281f76117 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cdns-dsi.c @@ -1028,7 +1028,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host, struct mipi_dsi_packet packet; int ret, i, tx_len, rx_len; - ret = pm_runtime_get_sync(host->dev); + ret = pm_runtime_resume_and_get(host->dev); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index d734d9402c35..c1926154eda8 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -1209,6 +1209,7 @@ static struct i2c_device_id lt9611_id[] = { { "lontium,lt9611", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, lt9611_id); static const struct of_device_id lt9611_match_table[] = { { .compatible = "lontium,lt9611" }, diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 66b67402f1ac..c65ca860712d 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -21,6 +21,7 @@ #include <linux/sys_soc.h> #include <linux/time64.h> +#include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> @@ -742,7 +743,9 @@ static int nwl_dsi_disable(struct nwl_dsi *dsi) return 0; } -static void nwl_dsi_bridge_disable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -803,17 +806,6 @@ static int nwl_dsi_get_dphy_params(struct nwl_dsi *dsi, return 0; } -static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* At least LCDIF + NWL needs active high sync */ - adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); - adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); - - return true; -} - static enum drm_mode_status nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, @@ -831,6 +823,24 @@ nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, return MODE_OK; } +static int nwl_dsi_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + + /* At least LCDIF + NWL needs active high sync */ + adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); + adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); + + /* Do a full modeset if crtc_state->active is changed to be true. */ + if (crtc_state->active_changed && crtc_state->active) + crtc_state->mode_changed = true; + + return 0; +} + static void nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, @@ -862,7 +872,9 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, drm_mode_debug_printmodeline(adjusted_mode); } -static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -897,7 +909,9 @@ static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) } } -static void nwl_dsi_bridge_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -942,14 +956,17 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge) } static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { - .pre_enable = nwl_dsi_bridge_pre_enable, - .enable = nwl_dsi_bridge_enable, - .disable = nwl_dsi_bridge_disable, - .mode_fixup = nwl_dsi_bridge_mode_fixup, - .mode_set = nwl_dsi_bridge_mode_set, - .mode_valid = nwl_dsi_bridge_mode_valid, - .attach = nwl_dsi_bridge_attach, - .detach = nwl_dsi_bridge_detach, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_check = nwl_dsi_bridge_atomic_check, + .atomic_pre_enable = nwl_dsi_bridge_atomic_pre_enable, + .atomic_enable = nwl_dsi_bridge_atomic_enable, + .atomic_disable = nwl_dsi_bridge_atomic_disable, + .mode_set = nwl_dsi_bridge_mode_set, + .mode_valid = nwl_dsi_bridge_mode_valid, + .attach = nwl_dsi_bridge_attach, + .detach = nwl_dsi_bridge_detach, }; static int nwl_dsi_parse_dt(struct nwl_dsi *dsi) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index deeed73f4ed6..3c55753bab16 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -602,7 +602,14 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux, !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) return 0; + /* Some branches advertise having 0 downstream ports, despite also advertising they have a + * downstream port present. The DP spec isn't clear on if this is allowed or not, but since + * some branches do it we need to handle it regardless. + */ len = drm_dp_downstream_port_count(dpcd); + if (!len) + return 0; + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) len *= 4; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index a08cc6b53bc2..861f16dfd1a3 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -94,6 +94,9 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port); static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port); static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr); +static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port, + struct drm_dp_mst_branch *branch); + #define DBG_PREFIX "[dp_mst]" #define DP_STR(x) [DP_ ## x] = #x @@ -2499,7 +2502,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, { struct drm_dp_mst_topology_mgr *mgr = mstb->mgr; struct drm_dp_mst_port *port; - int old_ddps, old_input, ret, i; + int old_ddps, ret; u8 new_pdt; bool new_mcs; bool dowork = false, create_connector = false; @@ -2531,7 +2534,6 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, } old_ddps = port->ddps; - old_input = port->input; port->input = conn_stat->input_port; port->ldps = conn_stat->legacy_device_plug_status; port->ddps = conn_stat->displayport_device_plug_status; @@ -2554,28 +2556,6 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, dowork = false; } - if (!old_input && old_ddps != port->ddps && !port->ddps) { - for (i = 0; i < mgr->max_payloads; i++) { - struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; - struct drm_dp_mst_port *port_validated; - - if (!vcpi) - continue; - - port_validated = - container_of(vcpi, struct drm_dp_mst_port, vcpi); - port_validated = - drm_dp_mst_topology_get_port_validated(mgr, port_validated); - if (!port_validated) { - mutex_lock(&mgr->payload_lock); - vcpi->num_slots = 0; - mutex_unlock(&mgr->payload_lock); - } else { - drm_dp_mst_topology_put_port(port_validated); - } - } - } - if (port->connector) drm_modeset_unlock(&mgr->base.lock); else if (create_connector) @@ -3385,6 +3365,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) struct drm_dp_mst_port *port; int i, j; int cur_slots = 1; + bool skip; mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { @@ -3399,6 +3380,16 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) port = container_of(vcpi, struct drm_dp_mst_port, vcpi); + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) { + drm_dbg_kms(mgr->dev, + "Virtual channel %d is not in current topology\n", + i); + continue; + } /* Validated ports don't matter if we're releasing * VCPI */ @@ -3406,8 +3397,16 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) port = drm_dp_mst_topology_get_port_validated( mgr, port); if (!port) { - mutex_unlock(&mgr->payload_lock); - return -EINVAL; + if (vcpi->num_slots == payload->num_slots) { + cur_slots += vcpi->num_slots; + payload->start_slot = req_payload.start_slot; + continue; + } else { + drm_dbg_kms(mgr->dev, + "Fail:set payload to invalid sink"); + mutex_unlock(&mgr->payload_lock); + return -EINVAL; + } } put_port = true; } @@ -3491,6 +3490,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) struct drm_dp_mst_port *port; int i; int ret = 0; + bool skip; mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { @@ -3500,6 +3500,13 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) + continue; + DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state); if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) { ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]); @@ -4581,9 +4588,18 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { + bool skip; + if (!port->vcpi.vcpi) return; + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) + return; + drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); port->vcpi.num_slots = 0; port->vcpi.pbn = 0; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 54d9876b5305..6ef4ea07d1bb 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -435,6 +435,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create const struct drm_mode_fb_cmd2 *cmd) { struct drm_gem_object *obj; + struct drm_framebuffer *fb; /* * Find the GEM object and thus the gtt range object that is @@ -445,7 +446,11 @@ static struct drm_framebuffer *psb_user_framebuffer_create return ERR_PTR(-ENOENT); /* Let the core code do all the work */ - return psb_framebuffer_create(dev, cmd, obj); + fb = psb_framebuffer_create(dev, cmd, obj); + if (IS_ERR(fb)) + drm_gem_object_put(obj); + + return fb; } static int psbfb_probe(struct drm_fb_helper *fb_helper, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index eb02ecb6e345..65d73eb5e155 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5080,7 +5080,7 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, if (size < sizeof(struct dp_sdp)) return -EINVAL; - memset(vsc, 0, size); + memset(vsc, 0, sizeof(*vsc)); if (sdp->sdp_header.HB0 != 0) return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index f08e25e95746..be27f9889431 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -299,10 +299,7 @@ static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, __i915_gem_object_pin_pages(pt->base); i915_gem_object_make_unshrinkable(pt->base); - if (lvl || - gen8_pt_count(*start, end) < I915_PDES || - intel_vgpu_active(vm->i915)) - fill_px(pt, vm->scratch[lvl]->encode); + fill_px(pt, vm->scratch[lvl]->encode); spin_lock(&pd->lock); if (likely(!pd->entry[idx])) { diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index b5937b39145a..cd71631bef0c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -348,7 +348,7 @@ static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt) if (intel_has_pending_fb_unpin(ggtt->vm.i915)) return ERR_PTR(-EAGAIN); - return ERR_PTR(-EDEADLK); + return ERR_PTR(-ENOBUFS); } int __i915_vma_pin_fence(struct i915_vma *vma) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a3d1617d7c67..b6bb5fc7d183 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -347,7 +347,7 @@ static void ingenic_drm_plane_enable(struct ingenic_drm *priv, unsigned int en_bit; if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) + if (plane != &priv->f0) en_bit = JZ_LCD_OSDC_F1EN; else en_bit = JZ_LCD_OSDC_F0EN; @@ -362,7 +362,7 @@ void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane) unsigned int en_bit; if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) + if (plane != &priv->f0) en_bit = JZ_LCD_OSDC_F1EN; else en_bit = JZ_LCD_OSDC_F0EN; @@ -389,8 +389,7 @@ void ingenic_drm_plane_config(struct device *dev, ingenic_drm_plane_enable(priv, plane); - if (priv->soc_info->has_osd && - plane->type == DRM_PLANE_TYPE_PRIMARY) { + if (priv->soc_info->has_osd && plane != &priv->f0) { switch (fourcc) { case DRM_FORMAT_XRGB1555: ctrl |= JZ_LCD_OSDCTRL_RGB555; @@ -423,7 +422,7 @@ void ingenic_drm_plane_config(struct device *dev, } if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) { + if (plane != &priv->f0) { xy_reg = JZ_REG_LCD_XYP1; size_reg = JZ_REG_LCD_SIZE1; } else { @@ -455,7 +454,7 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, height = state->src_h >> 16; cpp = state->fb->format->cpp[0]; - if (priv->soc_info->has_osd && plane->type == DRM_PLANE_TYPE_OVERLAY) + if (!priv->soc_info->has_osd || plane == &priv->f0) hwdesc = priv->dma_hwdesc_f0; else hwdesc = priv->dma_hwdesc_f1; @@ -692,6 +691,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) const struct jz_soc_info *soc_info; struct ingenic_drm *priv; struct clk *parent_clk; + struct drm_plane *primary; struct drm_bridge *bridge; struct drm_panel *panel; struct drm_encoder *encoder; @@ -784,9 +784,11 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) if (soc_info->has_osd) priv->ipu_plane = drm_plane_from_index(drm, 0); - drm_plane_helper_add(&priv->f1, &ingenic_drm_plane_helper_funcs); + primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0; + + drm_plane_helper_add(primary, &ingenic_drm_plane_helper_funcs); - ret = drm_universal_plane_init(drm, &priv->f1, 1, + ret = drm_universal_plane_init(drm, primary, 1, &ingenic_drm_primary_plane_funcs, ingenic_drm_primary_formats, ARRAY_SIZE(ingenic_drm_primary_formats), @@ -798,7 +800,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); - ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1, + ret = drm_crtc_init_with_planes(drm, &priv->crtc, primary, NULL, &ingenic_drm_crtc_funcs, NULL); if (ret) { dev_err(dev, "Failed to init CRTC: %i\n", ret); diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index fc8c6e970ee3..06fd118b1444 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -753,7 +753,7 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d) err = drm_universal_plane_init(drm, plane, 1, &ingenic_ipu_plane_funcs, soc_info->formats, soc_info->num_formats, - NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + NULL, DRM_PLANE_TYPE_OVERLAY, NULL); if (err) { dev_err(dev, "Failed to init plane: %i\n", err); return err; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index ac038572164d..dfd5ed15a7f4 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -274,7 +274,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) drm_connector_list_iter_end(&conn_iter); } - ret = pm_runtime_get_sync(crtc->dev->dev); + ret = pm_runtime_resume_and_get(crtc->dev->dev); if (ret < 0) { DRM_ERROR("Failed to enable power domain: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index dbf8d429223e..2f75e3905202 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -88,8 +88,6 @@ static int mdp4_hw_init(struct msm_kms *kms) if (mdp4_kms->rev > 1) mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1); - dev->mode_config.allow_fb_modifiers = true; - out: pm_runtime_put_sync(dev->dev); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index da3cc1d8c331..ee1dbb2b84af 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -347,6 +347,12 @@ enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane) return mdp4_plane->pipe; } +static const uint64_t supported_format_modifiers[] = { + DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + /* initialize plane */ struct drm_plane *mdp4_plane_init(struct drm_device *dev, enum mdp4_pipe pipe_id, bool private_plane) @@ -375,7 +381,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, mdp4_plane->formats, mdp4_plane->nformats, - NULL, type, NULL); + supported_format_modifiers, type, NULL); if (ret) goto fail; diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 0143d539f8f8..ee22cd25d3e3 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -10,7 +10,6 @@ config DRM_MXSFB depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_CMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index bceb48a2dfca..f2ad6f49fb72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -700,7 +700,6 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.preferred_depth = 24; dev->mode_config.prefer_shadow = 1; - dev->mode_config.allow_fb_modifiers = true; if (drm->client.device.info.chipset < 0x11) dev->mode_config.async_page_flip = false; diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index ef70140c5b09..873cbd38e6d3 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -706,9 +706,7 @@ static int nt35510_power_on(struct nt35510 *nt) if (ret) return ret; - ret = nt35510_read_id(nt); - if (ret) - return ret; + nt35510_read_id(nt); /* Set up stuff in manufacturer control, page 1 */ ret = nt35510_send_long(nt, dsi, MCS_CMD_MAUCCTR, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e0ae911ef427..71bdafac9210 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1334,6 +1334,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, /* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */ if (obj->import_attach) { DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n"); + drm_gem_object_put(obj); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4cd30613fa1d..e9df5e8ef0a5 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -416,13 +416,13 @@ radeon_pci_shutdown(struct pci_dev *pdev) if (radeon_device_is_virtual()) radeon_pci_remove(pdev); -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64) /* * Some adapters need to be suspended before a * shutdown occurs in order to prevent an error - * during kexec. - * Make this power specific becauase it breaks - * some non-power boards. + * during kexec, shutdown or reboot. + * Make this power and Loongson specific because + * it breaks some other boards. */ radeon_suspend_kms(pci_get_drvdata(pdev), true, true, false); #endif diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 75a76408cb29..d0c9610ad220 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -243,7 +243,6 @@ struct dw_mipi_dsi_rockchip { struct dw_mipi_dsi *dmd; const struct rockchip_dw_dsi_chip_data *cdata; struct dw_mipi_dsi_plat_data pdata; - int devcnt; }; struct dphy_pll_parameter_map { @@ -1141,9 +1140,6 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) { struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev); - if (dsi->devcnt == 0) - component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops); - dw_mipi_dsi_remove(dsi->dmd); return 0; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 80053d91a301..a6fe03c3748a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -349,8 +349,8 @@ static const struct vop_win_phy rk3066_win0_data = { .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19), .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), @@ -361,13 +361,12 @@ static const struct vop_win_phy rk3066_win0_data = { }; static const struct vop_win_phy rk3066_win1_data = { - .scl = &rk3066_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23), .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), @@ -382,8 +381,8 @@ static const struct vop_win_phy rk3066_win2_data = { .nformats = ARRAY_SIZE(formats_win_lite), .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27), .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), @@ -408,6 +407,9 @@ static const struct vop_common rk3066_common = { .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10), .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), + .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), }; static const struct vop_win_data rk3066_vop_win_data[] = { @@ -505,7 +507,10 @@ static const struct vop_common rk3188_common = { .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27), .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), - .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), + .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), + .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), }; static const struct vop_win_data rk3188_vop_win_data[] = { diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 146380118962..3f7f761df4cd 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -113,7 +113,8 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) rmb(); /* for list_empty to work without lock */ if (list_empty(&entity->list) || - spsc_queue_count(&entity->job_queue) == 0) + spsc_queue_count(&entity->job_queue) == 0 || + entity->stopped) return true; return false; @@ -218,11 +219,16 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) { struct drm_sched_job *job; + struct dma_fence *f; int r; while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) { struct drm_sched_fence *s_fence = job->s_fence; + /* Wait for all dependencies to avoid data corruptions */ + while ((f = job->sched->ops->dependency(job, entity))) + dma_fence_wait(f, false); + drm_sched_fence_scheduled(s_fence); dma_fence_set_error(&s_fence->finished, -ESRCH); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 7111e0f527b0..b6c2757c3d83 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -887,9 +887,33 @@ EXPORT_SYMBOL(drm_sched_init); */ void drm_sched_fini(struct drm_gpu_scheduler *sched) { + struct drm_sched_entity *s_entity; + int i; + if (sched->thread) kthread_stop(sched->thread); + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + struct drm_sched_rq *rq = &sched->sched_rq[i]; + + if (!rq) + continue; + + spin_lock(&rq->lock); + list_for_each_entry(s_entity, &rq->entities, list) + /* + * Prevents reinsertion and marks job_queue as idle, + * it will removed from rq in drm_sched_entity_fini + * eventually + */ + s_entity->stopped = true; + spin_unlock(&rq->lock); + + } + + /* Wakeup everyone stuck in drm_sched_entity_flush for this scheduler */ + wake_up_all(&sched->job_scheduled); + /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&sched->work_tdr); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3aa9a7406085..ceb86338c003 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -947,6 +947,11 @@ static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = { .atomic_disable = tegra_cursor_atomic_disable, }; +static const uint64_t linear_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, struct tegra_dc *dc) { @@ -975,7 +980,7 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_plane_funcs, formats, - num_formats, NULL, + num_formats, linear_modifiers, DRM_PLANE_TYPE_CURSOR, NULL); if (err < 0) { kfree(plane); @@ -1094,7 +1099,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_plane_funcs, formats, - num_formats, NULL, type, NULL); + num_formats, linear_modifiers, + type, NULL); if (err < 0) { kfree(plane); return ERR_PTR(err); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e4baf07992a4..2c6ebc328b24 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1127,8 +1127,6 @@ static int host1x_drm_probe(struct host1x_device *dev) drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; - drm->mode_config.allow_fb_modifiers = true; - drm->mode_config.normalize_zpos = true; drm->mode_config.funcs = &tegra_drm_mode_config_funcs; diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 1d2416d466a3..f4ccca922e44 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1001,7 +1001,7 @@ static const struct vc4_pv_data bcm2711_pv3_data = { .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { - [0] = VC4_ENCODER_TYPE_VEC, + [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, }, }; @@ -1042,6 +1042,9 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm, struct vc4_encoder *vc4_encoder; int i; + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) + continue; + vc4_encoder = to_vc4_encoder(encoder); for (i = 0; i < ARRAY_SIZE(pv_data->encoder_types); i++) { if (vc4_encoder->type == encoder_types[i]) { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index c5f2944d5bc6..9809c3a856c6 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -837,7 +837,7 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, void vc4_crtc_reset(struct drm_crtc *crtc); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_get_margins(struct drm_crtc_state *state, - unsigned int *right, unsigned int *left, + unsigned int *left, unsigned int *right, unsigned int *top, unsigned int *bottom); /* vc4_debugfs.c */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 25a09aaf5883..c58b8840090a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -627,7 +627,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) unsigned long pixel_rate, hsm_rate; int ret; - ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); + ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); return; @@ -1807,6 +1807,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (vc4_hdmi->variant->reset) vc4_hdmi->variant->reset(vc4_hdmi); + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || + of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && + HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) { + clk_prepare_enable(vc4_hdmi->pixel_clock); + clk_prepare_enable(vc4_hdmi->hsm_clock); + clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); + } + pm_runtime_enable(dev); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 849dcafbfff1..d13502ae973d 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -503,7 +503,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) return ret; encoder = &txp->connector.encoder; - encoder->possible_crtcs |= drm_crtc_mask(crtc); + encoder->possible_crtcs = drm_crtc_mask(crtc); ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0, dev_name(dev), txp); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index eed57a931309..a28b01f92793 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -209,6 +209,7 @@ err_scanouts: err_vbufs: vgdev->vdev->config->del_vqs(vgdev->vdev); err_vqs: + dev->dev_private = NULL; kfree(vgdev); return ret; } diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig index 90ebaedc11fd..aa8594190b50 100644 --- a/drivers/gpu/drm/zte/Kconfig +++ b/drivers/gpu/drm/zte/Kconfig @@ -3,7 +3,6 @@ config DRM_ZTE tristate "DRM Support for ZTE SoCs" depends on DRM && ARCH_ZX select DRM_KMS_CMA_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_HELPER select SND_SOC_HDMI_CODEC if SND_SOC select VIDEOMODE_HELPERS |