diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 05:08:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 05:08:49 +0000 |
commit | 76047c0312414915035f4ebbaa533fe3817a21e0 (patch) | |
tree | 86f79ba3c1f753b1d39be793455035794fade031 /drivers/gpu | |
parent | Adding upstream version 6.8.11. (diff) | |
download | linux-76047c0312414915035f4ebbaa533fe3817a21e0.tar.xz linux-76047c0312414915035f4ebbaa533fe3817a21e0.zip |
Adding upstream version 6.8.12.upstream/6.8.12
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/gpu')
56 files changed, 317 insertions, 132 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index daa66eb4f7..b1e2dd52e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -220,7 +220,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > kfd_mem_limit.max_ttm_mem_limit) || (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed > - vram_size - reserved_for_pt)) { + vram_size - reserved_for_pt - atomic64_read(&adev->vram_pin_size))) { ret = -ENOMEM; goto release; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index da48b6da01..420e5bc44e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -1129,6 +1129,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev, return; amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id); + del_timer_sync(&ring->fence_drv.fallback_timer); amdgpu_ring_fini(ring); kfree(ring); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 9e5526046a..3af505e8cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -608,6 +608,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev, else amdgpu_bo_placement_from_domain(bo, bp->domain); if (bp->type == ttm_bo_type_kernel) + bo->tbo.priority = 2; + else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE)) bo->tbo.priority = 1; if (!bp->destroy) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index dcdecb18b2..42392a97da 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -9194,7 +9194,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = { 7 + /* PIPELINE_SYNC */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* VM_FLUSH */ + 4 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ 20 + /* GDS switch */ 4 + /* double SWITCH_BUFFER, @@ -9285,7 +9285,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = { 7 + /* gfx_v10_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v10_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */ .emit_ib = gfx_v10_0_ring_emit_ib_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 0afe86bcc9..6a6fc422e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -6110,7 +6110,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = { 7 + /* PIPELINE_SYNC */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* VM_FLUSH */ + 4 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ 20 + /* GDS switch */ 5 + /* COND_EXEC */ @@ -6195,7 +6195,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = { 7 + /* gfx_v11_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v11_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */ .emit_ib = gfx_v11_0_ring_emit_ib_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 3bc6943365..153932c1f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -6991,7 +6991,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */ 7 + /* gfx_v9_0_emit_mem_sync */ 5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */ @@ -7029,7 +7028,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */ .emit_fence = gfx_v9_0_ring_emit_fence_kiq, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index bdc01ca960..5c8d81bfce 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, start = start_mgr << PAGE_SHIFT; end = (last_mgr + 1) << PAGE_SHIFT; + r = amdgpu_amdkfd_reserve_mem_limit(node->adev, + prange->npages * PAGE_SIZE, + KFD_IOC_ALLOC_MEM_FLAGS_VRAM, + node->xcp ? node->xcp->id : 0); + if (r) { + dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r); + return -ENOSPC; + } + r = svm_range_vram_node_new(node, prange, true); if (r) { dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r); - return r; + goto out; } ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT; @@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, svm_range_vram_node_free(prange); } +out: + amdgpu_amdkfd_unreserve_mem_limit(node->adev, + prange->npages * PAGE_SIZE, + KFD_IOC_ALLOC_MEM_FLAGS_VRAM, + node->xcp ? node->xcp->id : 0); return r < 0 ? r : 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 58c1fe5421..451bb058cc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -829,6 +829,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) if (process) { pr_debug("Process already found\n"); } else { + /* If the process just called exec(3), it is possible that the + * cleanup of the kfd_process (following the release of the mm + * of the old process image) is still in the cleanup work queue. + * Make sure to drain any job before trying to recreate any + * resource for this process. + */ + flush_workqueue(kfd_process_wq); + process = create_process(thread); if (IS_ERR(process)) goto out; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index c50a0dc9c9..3320507820 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3424,7 +3424,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange, mm, KFD_MIGRATE_TRIGGER_PREFETCH); *migrated = !r; - return r; + return 0; } int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence) 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 9044214dfd..c4ba397f8c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3010,6 +3010,7 @@ static int dm_resume(void *handle) dc_stream_release(dm_new_crtc_state->stream); dm_new_crtc_state->stream = NULL; } + dm_new_crtc_state->base.color_mgmt_changed = true; } for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 644da46373..5506cf9b36 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -145,6 +145,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, */ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; if (safe_to_lower) { + if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) { + dcn315_smu_set_dtbclk(clk_mgr, false); + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; + } /* check that we're not already in lower */ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { display_count = dcn315_get_active_display_cnt_wa(dc, context); @@ -160,6 +164,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, } } } else { + if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) { + dcn315_smu_set_dtbclk(clk_mgr, true); + clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; + } /* check that we're not already in D0 */ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) { union display_idle_optimization_u idle_info = { 0 }; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index bbdbc78161..39c63565ba 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -696,8 +696,12 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, * since we calculate mode support based on softmax being the max UCLK * frequency. */ - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, - dc->clk_mgr->bw_params->dc_mode_softmax_memclk); + if (dc->debug.disable_dc_mode_overwrite) { + dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz); + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz); + } else + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, + dc->clk_mgr->bw_params->dc_mode_softmax_memclk); } else { dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz); } @@ -730,8 +734,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */ if (clk_mgr_base->clks.p_state_change_support && (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) && - !dc->work_arounds.clock_update_disable_mask.uclk) + !dc->work_arounds.clock_update_disable_mask.uclk) { + if (dc->clk_mgr->dc_mode_softmax_enabled && dc->debug.disable_dc_mode_overwrite) + dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, + max((int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz))); + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)); + } if (clk_mgr_base->clks.num_ways != new_clocks->num_ways && clk_mgr_base->clks.num_ways > new_clocks->num_ways) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 3c3d613c5f..040b5c2a57 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1804,6 +1804,9 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } + if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) + return false; + if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) { DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); return false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 3538973bd0..c0372aa4ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -382,6 +382,11 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx, i += increment) { if (j == hw_points - 1) break; + if (i >= TRANSFER_FUNC_POINTS) { + DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n", + i, TRANSFER_FUNC_POINTS); + return false; + } rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index deb6d162a2..7307b7b8d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -291,6 +291,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { .do_urgent_latency_adjustment = false, .urgent_latency_adjustment_fabric_clock_component_us = 0, .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, + .dispclk_dppclk_vco_speed_mhz = 2400.0, .num_chans = 4, .dummy_pstate_latency_us = 10.0 }; @@ -438,6 +439,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = { .do_urgent_latency_adjustment = false, .urgent_latency_adjustment_fabric_clock_component_us = 0, .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, + .dispclk_dppclk_vco_speed_mhz = 2500.0, }; void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 46cbb5a6c8..1a3c212ae6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -999,8 +999,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, if (pipe_ctx->plane_res.dpp) update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false; - if ((pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) && - pipe_ctx->plane_res.mpcc_inst >= 0) + if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false; if (pipe_ctx->stream_res.dsc) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index 5491b707ce..5a965c26bf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c @@ -270,7 +270,7 @@ static void set_usb4_req_bw_req(struct dc_link *link, int req_bw) /* Error check whether requested and allocated are equal */ req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity); - if (req_bw == link->dpia_bw_alloc_config.allocated_bw) { + if (req_bw && (req_bw == link->dpia_bw_alloc_config.allocated_bw)) { DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n", __func__, link->link_index); } @@ -341,6 +341,14 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link) ret = true; init_usb4_bw_struct(link); link->dpia_bw_alloc_config.bw_alloc_enabled = true; + + /* + * During DP tunnel creation, CM preallocates BW and reduces estimated BW of other + * DPIA. CM release preallocation only when allocation is complete. Do zero alloc + * to make the CM to release preallocation and update estimated BW correctly for + * all DPIAs per host router + */ + link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, 0); } } diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index f9c5bc624b..f81f611091 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -2451,6 +2451,7 @@ static bool dcn20_resource_construct( dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; /* Color pipeline capabilities */ dc->caps.color.dpp.dcn_arch = 1; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 78491b04df..ddb11eb8c3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -2205,6 +2205,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table return sizeof(*gpu_metrics); } +static void smu_v13_0_6_restore_pci_config(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < 16; i++) + pci_write_config_dword(adev->pdev, i * 4, + adev->pdev->saved_config_space[i]); + pci_restore_msi_state(adev->pdev); +} + static int smu_v13_0_6_mode2_reset(struct smu_context *smu) { int ret = 0, index; @@ -2226,6 +2237,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu) /* Restore the config space saved during init */ amdgpu_device_load_pci_state(adev->pdev); + /* Certain platforms have switches which assign virtual BAR values to + * devices. OS uses the virtual BAR values and device behind the switch + * is assgined another BAR value. When device's config space registers + * are queried, switch returns the virtual BAR values. When mode-2 reset + * is performed, switch is unaware of it, and will continue to return + * the same virtual values to the OS.This affects + * pci_restore_config_space() API as it doesn't write the value saved if + * the current value read from config space is the same as what is + * saved. As a workaround, make sure the config space is restored + * always. + */ + if (!(adev->flags & AMD_IS_APU)) + smu_v13_0_6_restore_pci_config(smu); + dev_dbg(smu->adev->dev, "wait for reset ack\n"); do { ret = smu_cmn_wait_for_response(smu); diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 626709bec6..2577f0cef8 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -72,7 +72,10 @@ static void malidp_mw_connector_reset(struct drm_connector *connector) __drm_atomic_helper_connector_destroy_state(connector->state); kfree(connector->state); - __drm_atomic_helper_connector_reset(connector, &mw_state->base); + connector->state = NULL; + + if (mw_state) + __drm_atomic_helper_connector_reset(connector, &mw_state->base); } static enum drm_connector_status diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 29d91493b1..c1191ef5e8 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2076,10 +2076,8 @@ static int anx7625_setup_dsi_device(struct anx7625_data *ctx) }; host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node); - if (!host) { - DRM_DEV_ERROR(dev, "fail to find dsi host.\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "fail to find dsi host.\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { @@ -2481,15 +2479,22 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, mutex_unlock(&ctx->aux_lock); } +static void +anx7625_audio_update_connector_status(struct anx7625_data *ctx, + enum drm_connector_status status); + static enum drm_connector_status anx7625_bridge_detect(struct drm_bridge *bridge) { struct anx7625_data *ctx = bridge_to_anx7625(bridge); struct device *dev = ctx->dev; + enum drm_connector_status status; DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n"); - return anx7625_sink_detect(ctx); + status = anx7625_sink_detect(ctx); + anx7625_audio_update_connector_status(ctx, status); + return status; } static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 7d47052745..bab8844c6f 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2057,6 +2057,9 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, mhdp_state = to_cdns_mhdp_bridge_state(new_state); mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode); + if (!mhdp_state->current_mode) + return; + drm_mode_set_name(mhdp_state->current_mode); dev_dbg(mhdp->dev, "%s: Enabling mode %s\n", __func__, mode->name); diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 82d23e4df0..ff3284b6b1 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -563,10 +563,8 @@ static int chipone_dsi_host_attach(struct chipone *icn) host = of_find_mipi_dsi_host_by_node(host_node); of_node_put(host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = mipi_dsi_device_register_full(host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 97d4af3d13..0b5b98d3e5 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -494,10 +494,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) }; host = of_find_mipi_dsi_host_by_node(lt->host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 9663601ce0..89bdd93875 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -760,10 +760,8 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, int ret; host = of_find_mipi_dsi_host_by_node(dsi_node); - if (!host) { - dev_err(lt9611->dev, "failed to find dsi host\n"); - return ERR_PTR(-EPROBE_DEFER); - } + if (!host) + return ERR_PTR(dev_err_probe(lt9611->dev, -EPROBE_DEFER, "failed to find dsi host\n")); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index e971b75e90..b803899126 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -265,10 +265,8 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc, int ret; host = of_find_mipi_dsi_host_by_node(dsi_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return ERR_PTR(-EPROBE_DEFER); - } + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 90a89d70d8..fea4f00a20 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -610,10 +610,8 @@ static int tc_attach_host(struct tc_data *tc) }; host = of_find_mipi_dsi_host_by_node(tc->host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index ca3348109b..6b559e0713 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -319,12 +319,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) .channel = 0, .node = NULL, }; + int ret; host = of_find_mipi_dsi_host_by_node(dlpc->host_node); - if (!host) { - DRM_DEV_ERROR(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dlpc->dsi = mipi_dsi_device_register_full(host, &info); if (IS_ERR(dlpc->dsi)) { @@ -336,7 +335,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) dlpc->dsi->format = MIPI_DSI_FMT_RGB565; dlpc->dsi->lanes = dlpc->dsi_lanes; - return devm_mipi_dsi_attach(dev, dlpc->dsi); + ret = devm_mipi_dsi_attach(dev, dlpc->dsi); + if (ret) + DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); + + return ret; } static int dlpc3433_probe(struct i2c_client *client) @@ -367,10 +370,8 @@ static int dlpc3433_probe(struct i2c_client *client) drm_bridge_add(&dlpc->bridge); ret = dlpc_host_attach(dlpc); - if (ret) { - DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); + if (ret) goto err_remove_bridge; - } return 0; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 62cc3893dc..1f6e929c2f 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1591,7 +1591,6 @@ static int ti_sn_pwm_probe(struct auxiliary_device *adev, pdata->pchip.ops = &ti_sn_pwm_ops; pdata->pchip.npwm = 1; pdata->pchip.of_xlate = of_pwm_single_xlate; - pdata->pchip.of_pwm_n_cells = 1; devm_pm_runtime_enable(&adev->dev); diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml index 9faf76e55a..da381257e7 100644 --- a/drivers/gpu/drm/ci/test.yml +++ b/drivers/gpu/drm/ci/test.yml @@ -237,11 +237,11 @@ i915:cml: i915:tgl: extends: - .i915 - parallel: 8 + parallel: 5 variables: - DEVICE_TYPE: asus-cx9400-volteer + DEVICE_TYPE: acer-cp514-2h-1130g7-volteer GPU_VERSION: tgl - RUNNER_TAG: mesa-ci-x86-64-lava-asus-cx9400-volteer + RUNNER_TAG: mesa-ci-x86-64-lava-acer-cp514-2h-1130g7-volteer .amdgpu: extends: diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index 26c188ce5f..fb80843e7f 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -533,6 +533,15 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, mutex_lock(&aux->hw_mutex); /* + * If the device attached to the aux bus is powered down then there's + * no reason to attempt a transfer. Error out immediately. + */ + if (aux->powered_down) { + ret = -EBUSY; + goto unlock; + } + + /* * The specification doesn't give any recommendation on how often to * retry native transactions. We used to retry 7 times like for * aux i2c transactions but real world devices this wasn't @@ -600,6 +609,29 @@ int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset) EXPORT_SYMBOL(drm_dp_dpcd_probe); /** + * drm_dp_dpcd_set_powered() - Set whether the DP device is powered + * @aux: DisplayPort AUX channel; for convenience it's OK to pass NULL here + * and the function will be a no-op. + * @powered: true if powered; false if not + * + * If the endpoint device on the DP AUX bus is known to be powered down + * then this function can be called to make future transfers fail immediately + * instead of needing to time out. + * + * If this function is never called then a device defaults to being powered. + */ +void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered) +{ + if (!aux) + return; + + mutex_lock(&aux->hw_mutex); + aux->powered_down = !powered; + mutex_unlock(&aux->hw_mutex); +} +EXPORT_SYMBOL(drm_dp_dpcd_set_powered); + +/** * drm_dp_dpcd_read() - read a series of bytes from the DPCD * @aux: DisplayPort AUX channel (SST or MST) * @offset: address of the (first) register to read @@ -1858,6 +1890,9 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, struct drm_dp_aux_msg msg; int err = 0; + if (aux->powered_down) + return -EBUSY; + dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES); memset(&msg, 0, sizeof(msg)); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 4f6f8c662d..ac502ea200 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -687,11 +687,17 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, */ list_for_each_entry_from(next, &encoder->bridge_chain, chain_node) { - if (next->pre_enable_prev_first) { + if (!next->pre_enable_prev_first) { next = list_prev_entry(next, chain_node); limit = next; break; } + + if (list_is_last(&next->chain_node, + &encoder->bridge_chain)) { + limit = next; + break; + } } /* Call these bridges in reverse order */ @@ -774,7 +780,7 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, /* Found first bridge that does NOT * request prev to be enabled first */ - limit = list_prev_entry(next, chain_node); + limit = next; break; } } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 69c6880402..9ef9a70a83 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -7345,7 +7345,7 @@ static void drm_parse_tiled_block(struct drm_connector *connector, static bool displayid_is_tiled_block(const struct displayid_iter *iter, const struct displayid_block *block) { - return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && + return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 && block->tag == DATA_BLOCK_TILED_DISPLAY) || (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY); diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 843a6dbda9..52a9314936 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -654,7 +654,7 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); * * Return: 0 on success or a negative error code on failure. */ -ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) { /* Note: Needs updating for non-default PPS or algorithm */ u8 tx[2] = { enable << 0, 0 }; @@ -679,8 +679,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode); * * Return: 0 on success or a negative error code on failure. */ -ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, - const struct drm_dsc_picture_parameter_set *pps) +int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, + const struct drm_dsc_picture_parameter_set *pps) { struct mipi_dsi_msg msg = { .channel = dsi->channel, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 9b8445d2a1..89cb6799b5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -632,8 +632,8 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) /* Disable TX clock gating on affected core revisions. */ if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) || etnaviv_is_model_rev(gpu, GC2000, 0x5108) || - etnaviv_is_model_rev(gpu, GC2000, 0x6202) || - etnaviv_is_model_rev(gpu, GC2000, 0x6203)) + etnaviv_is_model_rev(gpu, GC7000, 0x6202) || + etnaviv_is_model_rev(gpu, GC7000, 0x6203)) pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX; /* Disable SE and RA clock gating on affected core revisions. */ diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c index b7fef3c797..4f99b4af87 100644 --- a/drivers/gpu/drm/imagination/pvr_vm_mips.c +++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c @@ -46,7 +46,7 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev) if (!mips_data) return -ENOMEM; - for (page_nr = 0; page_nr < ARRAY_SIZE(mips_data->pt_pages); page_nr++) { + for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) { mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO); if (!mips_data->pt_pages[page_nr]) { err = -ENOMEM; @@ -102,7 +102,7 @@ pvr_vm_mips_fini(struct pvr_device *pvr_dev) int page_nr; vunmap(mips_data->pt); - for (page_nr = ARRAY_SIZE(mips_data->pt_pages) - 1; page_nr >= 0; page_nr--) { + for (page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) { dma_unmap_page(from_pvr_device(pvr_dev)->dev, mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 3d17de34d7..d398fa1871 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -992,10 +992,10 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->mmsys_dev = priv->mmsys_dev; mtk_crtc->ddp_comp_nr = path_len; - mtk_crtc->ddp_comp = devm_kmalloc_array(dev, - mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), - sizeof(*mtk_crtc->ddp_comp), - GFP_KERNEL); + mtk_crtc->ddp_comp = devm_kcalloc(dev, + mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), + sizeof(*mtk_crtc->ddp_comp), + GFP_KERNEL); if (!mtk_crtc->ddp_comp) return -ENOMEM; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 4f2e3feabc..1bf229615b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -38,6 +38,9 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, size = round_up(size, PAGE_SIZE); + if (size == 0) + return ERR_PTR(-EINVAL); + mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL); if (!mtk_gem_obj) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 2a82119eb5..2a942dc6a6 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -790,13 +790,13 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq, FREQ_1000_1001(params[i].pixel_freq)); DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n", i, params[i].phy_freq, - FREQ_1000_1001(params[i].phy_freq/10)*10); + FREQ_1000_1001(params[i].phy_freq/1000)*1000); /* Match strict frequency */ if (phy_freq == params[i].phy_freq && vclk_freq == params[i].vclk_freq) return MODE_OK; /* Match 1000/1001 variant */ - if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) && + if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/1000)*1000) && vclk_freq == FREQ_1000_1001(params[i].vclk_freq)) return MODE_OK; } @@ -1070,7 +1070,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, for (freq = 0 ; params[freq].pixel_freq ; ++freq) { if ((phy_freq == params[freq].phy_freq || - phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) && + phy_freq == FREQ_1000_1001(params[freq].phy_freq/1000)*1000) && (vclk_freq == params[freq].vclk_freq || vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) { if (vclk_freq != params[freq].vclk_freq) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 03f4951c49..e67a80d569 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -35,6 +35,7 @@ struct dp_aux_private { bool no_send_stop; bool initted; bool is_edp; + bool enable_xfers; u32 offset; u32 segment; @@ -302,6 +303,17 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, } /* + * If we're using DP and an external display isn't connected then the + * transfer won't succeed. Return right away. If we don't do this we + * can end up with long timeouts if someone tries to access the DP AUX + * character device when no DP device is connected. + */ + if (!aux->is_edp && !aux->enable_xfers) { + ret = -ENXIO; + goto exit; + } + + /* * For eDP it's important to give a reasonably long wait here for HPD * to be asserted. This is because the panel driver may have _just_ * turned on the panel and then tried to do an AUX transfer. The panel @@ -433,6 +445,14 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux) return IRQ_HANDLED; } +void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled) +{ + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + aux->enable_xfers = enabled; +} + void dp_aux_reconfig(struct drm_dp_aux *dp_aux) { struct dp_aux_private *aux; diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index 511305da4f..f3052cb433 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -12,6 +12,7 @@ int dp_aux_register(struct drm_dp_aux *dp_aux); void dp_aux_unregister(struct drm_dp_aux *dp_aux); irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux); +void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled); void dp_aux_init(struct drm_dp_aux *dp_aux); void dp_aux_deinit(struct drm_dp_aux *dp_aux); void dp_aux_reconfig(struct drm_dp_aux *dp_aux); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index fb588fde29..780e9747be 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1019,14 +1019,14 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) if (ret) return ret; - if (voltage_swing_level >= DP_TRAIN_VOLTAGE_SWING_MAX) { + if (voltage_swing_level >= DP_TRAIN_LEVEL_MAX) { drm_dbg_dp(ctrl->drm_dev, "max. voltage swing level reached %d\n", voltage_swing_level); max_level_reached |= DP_TRAIN_MAX_SWING_REACHED; } - if (pre_emphasis_level >= DP_TRAIN_PRE_EMPHASIS_MAX) { + if (pre_emphasis_level >= DP_TRAIN_LEVEL_MAX) { drm_dbg_dp(ctrl->drm_dev, "max. pre-emphasis level reached %d\n", pre_emphasis_level); @@ -1117,7 +1117,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl, } if (ctrl->link->phy_params.v_level >= - DP_TRAIN_VOLTAGE_SWING_MAX) { + DP_TRAIN_LEVEL_MAX) { DRM_ERROR_RATELIMITED("max v_level reached\n"); return -EAGAIN; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 78464c395c..0840860336 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -565,6 +565,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) int ret; struct platform_device *pdev = dp->dp_display.pdev; + dp_aux_enable_xfers(dp->aux, true); + mutex_lock(&dp->event_mutex); state = dp->hpd_state; @@ -630,6 +632,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) u32 state; struct platform_device *pdev = dp->dp_display.pdev; + dp_aux_enable_xfers(dp->aux, false); + mutex_lock(&dp->event_mutex); state = dp->hpd_state; diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 49dfac1fd1..ea911d9244 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -1109,6 +1109,7 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) { int i; + u8 max_p_level; int v_max = 0, p_max = 0; struct dp_link_private *link; @@ -1140,30 +1141,29 @@ int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) * Adjust the voltage swing and pre-emphasis level combination to within * the allowable range. */ - if (dp_link->phy_params.v_level > DP_TRAIN_VOLTAGE_SWING_MAX) { + if (dp_link->phy_params.v_level > DP_TRAIN_LEVEL_MAX) { drm_dbg_dp(link->drm_dev, "Requested vSwingLevel=%d, change to %d\n", dp_link->phy_params.v_level, - DP_TRAIN_VOLTAGE_SWING_MAX); - dp_link->phy_params.v_level = DP_TRAIN_VOLTAGE_SWING_MAX; + DP_TRAIN_LEVEL_MAX); + dp_link->phy_params.v_level = DP_TRAIN_LEVEL_MAX; } - if (dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_MAX) { + if (dp_link->phy_params.p_level > DP_TRAIN_LEVEL_MAX) { drm_dbg_dp(link->drm_dev, "Requested preEmphasisLevel=%d, change to %d\n", dp_link->phy_params.p_level, - DP_TRAIN_PRE_EMPHASIS_MAX); - dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_MAX; + DP_TRAIN_LEVEL_MAX); + dp_link->phy_params.p_level = DP_TRAIN_LEVEL_MAX; } - if ((dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_LVL_1) - && (dp_link->phy_params.v_level == - DP_TRAIN_VOLTAGE_SWING_LVL_2)) { + max_p_level = DP_TRAIN_LEVEL_MAX - dp_link->phy_params.v_level; + if (dp_link->phy_params.p_level > max_p_level) { drm_dbg_dp(link->drm_dev, "Requested preEmphasisLevel=%d, change to %d\n", dp_link->phy_params.p_level, - DP_TRAIN_PRE_EMPHASIS_LVL_1); - dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_LVL_1; + max_p_level); + dp_link->phy_params.p_level = max_p_level; } drm_dbg_dp(link->drm_dev, "adjusted: v_level=%d, p_level=%d\n", diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 9dd4dd9265..79c3a02b8d 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -19,19 +19,7 @@ struct dp_link_info { unsigned long capabilities; }; -enum dp_link_voltage_level { - DP_TRAIN_VOLTAGE_SWING_LVL_0 = 0, - DP_TRAIN_VOLTAGE_SWING_LVL_1 = 1, - DP_TRAIN_VOLTAGE_SWING_LVL_2 = 2, - DP_TRAIN_VOLTAGE_SWING_MAX = DP_TRAIN_VOLTAGE_SWING_LVL_2, -}; - -enum dp_link_preemaphasis_level { - DP_TRAIN_PRE_EMPHASIS_LVL_0 = 0, - DP_TRAIN_PRE_EMPHASIS_LVL_1 = 1, - DP_TRAIN_PRE_EMPHASIS_LVL_2 = 2, - DP_TRAIN_PRE_EMPHASIS_MAX = DP_TRAIN_PRE_EMPHASIS_LVL_2, -}; +#define DP_TRAIN_LEVEL_MAX 3 struct dp_link_test_video { u32 test_video_pattern; diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c index 18de2f17e2..6494e82707 100644 --- a/drivers/gpu/drm/mxsfb/lcdif_drv.c +++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c @@ -340,6 +340,9 @@ static int __maybe_unused lcdif_suspend(struct device *dev) if (ret) return ret; + if (pm_runtime_suspended(dev)) + return 0; + return lcdif_rpm_suspend(dev); } @@ -347,7 +350,8 @@ static int __maybe_unused lcdif_resume(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - lcdif_rpm_resume(dev); + if (!pm_runtime_suspended(dev)) + lcdif_rpm_resume(dev); return drm_mode_config_helper_resume(drm); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c index 6a0a4d3b89..027867c2a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c @@ -1080,7 +1080,7 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize) ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl)); if (ret) { nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl); - return PTR_ERR(ctrl); + return ret; } memcpy(data, ctrl->data, size); diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig index b715301ec7..6c49270cb2 100644 --- a/drivers/gpu/drm/omapdrm/Kconfig +++ b/drivers/gpu/drm/omapdrm/Kconfig @@ -4,7 +4,7 @@ config DRM_OMAP depends on DRM && OF depends on ARCH_OMAP2PLUS select DRM_KMS_HELPER - select FB_DMAMEM_HELPERS if DRM_FBDEV_EMULATION + select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION select VIDEOMODE_HELPERS select HDMI default n diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 6b08b137af..523be34682 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -51,6 +51,10 @@ static void pan_worker(struct work_struct *work) omap_gem_roll(bo, fbi->var.yoffset * npages); } +FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(omap_fbdev, + drm_fb_helper_damage_range, + drm_fb_helper_damage_area) + static int omap_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi) { @@ -78,11 +82,9 @@ fallback: static int omap_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) { - struct drm_fb_helper *helper = info->par; - struct drm_framebuffer *fb = helper->fb; - struct drm_gem_object *bo = drm_gem_fb_get_obj(fb, 0); + vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); - return drm_gem_mmap_obj(bo, omap_gem_mmap_size(bo), vma); + return fb_deferred_io_mmap(info, vma); } static void omap_fbdev_fb_destroy(struct fb_info *info) @@ -94,6 +96,7 @@ static void omap_fbdev_fb_destroy(struct fb_info *info) DBG(); + fb_deferred_io_cleanup(info); drm_fb_helper_fini(helper); omap_gem_unpin(bo); @@ -104,15 +107,19 @@ static void omap_fbdev_fb_destroy(struct fb_info *info) kfree(fbdev); } +/* + * For now, we cannot use FB_DEFAULT_DEFERRED_OPS and fb_deferred_io_mmap() + * because we use write-combine. + */ static const struct fb_ops omap_fb_ops = { .owner = THIS_MODULE, - __FB_DEFAULT_DMAMEM_OPS_RDWR, + __FB_DEFAULT_DEFERRED_OPS_RDWR(omap_fbdev), .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, .fb_setcmap = drm_fb_helper_setcmap, .fb_blank = drm_fb_helper_blank, .fb_pan_display = omap_fbdev_pan_display, - __FB_DEFAULT_DMAMEM_OPS_DRAW, + __FB_DEFAULT_DEFERRED_OPS_DRAW(omap_fbdev), .fb_ioctl = drm_fb_helper_ioctl, .fb_mmap = omap_fbdev_fb_mmap, .fb_destroy = omap_fbdev_fb_destroy, @@ -213,6 +220,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, fbi->fix.smem_start = dma_addr; fbi->fix.smem_len = bo->size; + /* deferred I/O */ + helper->fbdefio.delay = HZ / 20; + helper->fbdefio.deferred_io = drm_fb_helper_deferred_io; + + fbi->fbdefio = &helper->fbdefio; + ret = fb_deferred_io_init(fbi); + if (ret) + goto fail; + /* if we have DMM, then we can use it for scrolling by just * shuffling pages around in DMM rather than doing sw blit. */ @@ -238,8 +254,20 @@ fail: return ret; } +static int omap_fbdev_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip) +{ + if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2)) + return 0; + + if (helper->fb->funcs->dirty) + return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1); + + return 0; +} + static const struct drm_fb_helper_funcs omap_fb_helper_funcs = { .fb_probe = omap_fbdev_create, + .fb_dirty = omap_fbdev_dirty, }; static struct drm_fb_helper *get_fb(struct fb_info *fbi) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index e5e3f0b9ca..49b8a2484d 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -397,6 +397,7 @@ static int panel_edp_suspend(struct device *dev) { struct panel_edp *p = dev_get_drvdata(dev); + drm_dp_dpcd_set_powered(p->aux, false); gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->supply); p->unprepared_time = ktime_get_boottime(); @@ -453,6 +454,7 @@ static int panel_edp_prepare_once(struct panel_edp *p) } gpiod_set_value_cansleep(p->enable_gpio, 1); + drm_dp_dpcd_set_powered(p->aux, true); delay = p->desc->delay.hpd_reliable; if (p->no_hpd) @@ -489,6 +491,7 @@ static int panel_edp_prepare_once(struct panel_edp *p) return 0; error: + drm_dp_dpcd_set_powered(p->aux, false); gpiod_set_value_cansleep(p->enable_gpio, 0); regulator_disable(p->supply); p->unprepared_time = ktime_get_boottime(); diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index 30919c872a..8e0f5c3e3b 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -295,8 +295,6 @@ static int ltk050h3148w_init_sequence(struct ltk050h3146w *ctx) mipi_dsi_dcs_write_seq(dsi, 0xbd, 0x00); mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xef); mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0x29); ret = mipi_dsi_dcs_set_tear_on(dsi, 1); if (ret < 0) { @@ -326,7 +324,8 @@ static const struct drm_display_mode ltk050h3148w_mode = { static const struct ltk050h3146w_desc ltk050h3148w_data = { .mode = <k050h3148w_mode, .init = ltk050h3148w_init_sequence, - .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO_BURST, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_BURST, }; static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c index 648ce92014..028fdac293 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c @@ -556,10 +556,8 @@ static int nt35950_probe(struct mipi_dsi_device *dsi) } dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r); of_node_put(dsi_r); - if (!dsi_r_host) { - dev_err(dev, "Cannot get secondary DSI host\n"); - return -EPROBE_DEFER; - } + if (!dsi_r_host) + return dev_err_probe(dev, -EPROBE_DEFER, "Cannot get secondary DSI host\n"); nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info); if (!nt->dsi[1]) { diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c index 5703f4712d..9c336c7156 100644 --- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c +++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c @@ -72,6 +72,7 @@ static int atana33xc20_suspend(struct device *dev) if (p->el3_was_on) atana33xc20_wait(p->el_on3_off_time, 150); + drm_dp_dpcd_set_powered(p->aux, false); ret = regulator_disable(p->supply); if (ret) return ret; @@ -93,6 +94,7 @@ static int atana33xc20_resume(struct device *dev) ret = regulator_enable(p->supply); if (ret) return ret; + drm_dp_dpcd_set_powered(p->aux, true); p->powered_on_time = ktime_get_boottime(); if (p->no_hpd) { @@ -107,19 +109,17 @@ static int atana33xc20_resume(struct device *dev) if (hpd_asserted < 0) ret = hpd_asserted; - if (ret) + if (ret) { dev_warn(dev, "Error waiting for HPD GPIO: %d\n", ret); - - return ret; - } - - if (p->aux->wait_hpd_asserted) { + goto error; + } + } else if (p->aux->wait_hpd_asserted) { ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US); - if (ret) + if (ret) { dev_warn(dev, "Controller error waiting for HPD: %d\n", ret); - - return ret; + goto error; + } } /* @@ -131,6 +131,12 @@ static int atana33xc20_resume(struct device *dev) * right times. */ return 0; + +error: + drm_dp_dpcd_set_powered(p->aux, false); + regulator_disable(p->supply); + + return ret; } static int atana33xc20_disable(struct drm_panel *panel) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 72fdab8adb..228c5c48e1 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2564,6 +2564,9 @@ static const struct panel_desc innolux_g121x1_l03 = { .unprepare = 200, .disable = 400, }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, }; static const struct display_timing innolux_g156hce_l01_timings = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index fdd768bbd4..62ebbdb162 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -706,6 +706,8 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, const struct drm_format_info *info; u16 hor_scl_mode, ver_scl_mode; u16 hscl_filter_mode, vscl_filter_mode; + uint16_t cbcr_src_w = src_w; + uint16_t cbcr_src_h = src_h; u8 gt2 = 0; u8 gt4 = 0; u32 val; @@ -763,27 +765,27 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win, vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode); if (info->is_yuv) { - src_w /= info->hsub; - src_h /= info->vsub; + cbcr_src_w /= info->hsub; + cbcr_src_h /= info->vsub; gt4 = 0; gt2 = 0; - if (src_h >= (4 * dst_h)) { + if (cbcr_src_h >= (4 * dst_h)) { gt4 = 1; - src_h >>= 2; - } else if (src_h >= (2 * dst_h)) { + cbcr_src_h >>= 2; + } else if (cbcr_src_h >= (2 * dst_h)) { gt2 = 1; - src_h >>= 1; + cbcr_src_h >>= 1; } - hor_scl_mode = scl_get_scl_mode(src_w, dst_w); - ver_scl_mode = scl_get_scl_mode(src_h, dst_h); + hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w); + ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h); - val = vop2_scale_factor(src_w, dst_w); + val = vop2_scale_factor(cbcr_src_w, dst_w); vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val); - val = vop2_scale_factor(src_h, dst_h); + val = vop2_scale_factor(cbcr_src_h, dst_h); vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val); vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f827f26543..eff4746570 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -2739,6 +2739,8 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) index = 1; addr = of_get_address(dev->of_node, index, NULL, NULL); + if (!addr) + return -EINVAL; vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |